// tell the cluster system that an object has been attacked void clustObjectAttacked(BASE_OBJECT *psObj) { if ((aClusterAttacked[psObj->cluster] + ATTACK_CB_PAUSE) < gameTime) { psScrCBTarget = psObj; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_ATTACKED); triggerEventAttacked(psObj, g_pProjLastAttacker); switch (psObj->type) { case OBJ_DROID: psLastDroidHit = (DROID *)psObj; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DROID_ATTACKED); psLastDroidHit = NULL; break; case OBJ_STRUCTURE: psLastStructHit = (STRUCTURE *)psObj; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_STRUCT_ATTACKED); psLastStructHit = NULL; break; default: ASSERT(!"invalid object type", "clustObjectAttacked: invalid object type"); return; } // and fire the sound effect (and/or...) for the added callback trigger we just processed triggerEventAttacked(psObj, g_pProjLastAttacker); aClusterAttacked[psObj->cluster] = gameTime; } }
void requestAlliance(uint8_t from, uint8_t to, bool prop, bool allowAudio) { if (prop && bMultiMessages) { sendAlliance(from, to, ALLIANCE_REQUESTED, false); return; // Wait for our message. } syncDebug("Request alliance %d %d", from, to); alliances[from][to] = ALLIANCE_REQUESTED; // We've asked alliances[to][from] = ALLIANCE_INVITATION; // They've been invited CBallFrom = from; CBallTo = to; eventFireCallbackTrigger((TRIGGER_TYPE) CALL_ALLIANCEOFFER); if (to == selectedPlayer) { CONPRINTF(ConsoleString, (ConsoleString, _("%s Requests An Alliance With You"), getPlayerName(from))); if (allowAudio) { audio_QueueTrack(ID_ALLIANCE_OFF); } } else if (from == selectedPlayer) { CONPRINTF(ConsoleString, (ConsoleString, _("You Invite %s To Form An Alliance"), getPlayerName(to))); if (allowAudio) { audio_QueueTrack(ID_ALLIANCE_OFF); } } }
void requestAlliance(uint8_t from, uint8_t to, BOOL prop, BOOL allowAudio) { alliances[from][to] = ALLIANCE_REQUESTED; // We've asked alliances[to][from] = ALLIANCE_INVITATION; // They've been invited CBallFrom = from; CBallTo = to; eventFireCallbackTrigger((TRIGGER_TYPE) CALL_ALLIANCEOFFER); if (to == selectedPlayer) { CONPRINTF(ConsoleString,(ConsoleString,_("%s Requests An Alliance With You"),getPlayerName(from))); if (allowAudio) { audio_QueueTrack(ID_ALLIANCE_OFF); } } else if (from == selectedPlayer) { CONPRINTF(ConsoleString,(ConsoleString,_("You Invite %s To Form An Alliance"),getPlayerName(to))); if (allowAudio) { audio_QueueTrack(ID_ALLIANCE_OFF); } } if (prop) { sendAlliance(from, to, ALLIANCE_REQUESTED, false); } }
static void intCleanUpIntelMap(void) { MESSAGE *psMessage, *psNext; //remove any research messages that have been read for (psMessage = apsMessages[selectedPlayer]; psMessage != NULL; psMessage = psNext) { psNext = psMessage->psNext; if (psMessage->type == MSG_RESEARCH && psMessage->read) { removeMessage(psMessage, selectedPlayer); } } resetIntelligencePauseState(); immediateMessage = false; cdAudio_Resume(); if (interpProcessorActive()) { debug(LOG_SCRIPT, "intCleanUpIntelMap: interpreter running, storing CALL_VIDEO_QUIT"); if(!msgStackPush(CALL_VIDEO_QUIT,-1,-1,"\0",-1,-1,NULL)) { debug(LOG_ERROR, "intCleanUpIntelMap() - msgStackPush - stack failed"); return; } } else { debug(LOG_SCRIPT, "intCleanUpIntelMap: not running"); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_VIDEO_QUIT); } }
void seq_StartNextFullScreenVideo(void) { bool bPlayedOK; currentPlaySeq++; if (currentPlaySeq >= MAX_SEQ_LIST) { bPlayedOK = false; } else { bPlayedOK = seq_StartFullScreenVideo(aSeqList[currentPlaySeq].pSeq, aSeqList[currentPlaySeq].pAudio, VIDEO_USER_CHOSEN_RESOLUTION); } if (bPlayedOK == false) { //don't do the callback if we're playing the win/lose video if (!getScriptWinLoseVideo()) { debug(LOG_SCRIPT, "*** Called video quit trigger!"); // Not sure this is correct... CHECK, since the callback should ONLY // be called when a video is playing (always?) if (seq_Playing()) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_VIDEO_QUIT); } } else { displayGameOver(getScriptWinLoseVideo() == PLAY_WIN); } } }
/*! * Preparations before entering the game loop * Would start the timer in an event based mainloop */ static void startGameLoop(void) { SetGameMode(GS_NORMAL); // Not sure what aLevelName is, in relation to game.map. But need to use aLevelName here, to be able to start the right map for campaign, and need game.hash, to start the right non-campaign map, if there are multiple identically named maps. if (!levLoadData(aLevelName, &game.hash, NULL, GTYPE_SCENARIO_START)) { debug( LOG_FATAL, "Shutting down after failure" ); exit(EXIT_FAILURE); } screen_StopBackDrop(); // Trap the cursor if cursor snapping is enabled if (war_GetTrapCursor()) { wzGrabMouse(); } // set a flag for the trigger/event system to indicate initialisation is complete gameInitialised = true; if (challengeActive) { addMissionTimerInterface(); } if (game.type == SKIRMISH) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL); } triggerEvent(TRIGGER_START_LEVEL); screen_disableMapPreview(); }
// Write a message to the console. bool recvTextMessage(NETQUEUE queue) { UDWORD playerIndex; char msg[MAX_CONSOLE_STRING_LENGTH]; char newmsg[MAX_CONSOLE_STRING_LENGTH]; memset(msg, 0x0, sizeof(msg)); memset(newmsg, 0x0, sizeof(newmsg)); NETbeginDecode(queue, NET_TEXTMSG); // Who this msg is from NETuint32_t(&playerIndex); // The message to send NETstring(newmsg, MAX_CONSOLE_STRING_LENGTH); NETend(); if (whosResponsible(playerIndex) != queue.index) { playerIndex = queue.index; // Fix corrupted playerIndex. } if (playerIndex >= MAX_PLAYERS || (!NetPlay.players[playerIndex].allocated && NetPlay.players[playerIndex].ai == AI_OPEN)) { return false; } sstrcpy(msg, NetPlay.players[playerIndex].name); // Seperator sstrcat(msg, ": "); // Add message sstrcat(msg, newmsg); addConsoleMessage(msg, DEFAULT_JUSTIFY, playerIndex); // Multiplayer message callback // Received a console message from a player, save MultiMsgPlayerFrom = playerIndex; MultiMsgPlayerTo = selectedPlayer; sstrcpy(MultiplayMsg, newmsg); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_AI_MSG); // make some noise! if (titleMode == MULTIOPTION || titleMode == MULTILIMIT) { audio_PlayTrack(FE_AUDIO_MESSAGEEND); } else if (!ingame.localJoiningInProgress) { audio_PlayTrack(ID_SOUND_MESSAGEEND); } return true; }
// tell the cluster system that an objects visibility has changed void clustObjectSeen(BASE_OBJECT *psObj, BASE_OBJECT *psViewer) { SDWORD player; for(player=0; player<MAX_PLAYERS; player++) { ASSERT(psObj->cluster != (UBYTE)~0, "object not in a cluster"); if ( (player != (SDWORD)psObj->player) && psObj->visible[player] && !(aClusterVisibility[psObj->cluster] & (1 << player))) { // DBPRINTF(("cluster %d (player %d) seen by player %d\n", // clustGetClusterID(psObj), psObj->player, player)); aClusterVisibility[psObj->cluster] |= 1 << player; psScrCBObjSeen = psObj; psScrCBObjViewer = psViewer; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_OBJ_SEEN); switch (psObj->type) { case OBJ_DROID: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DROID_SEEN); break; case OBJ_STRUCTURE: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_STRUCT_SEEN); break; case OBJ_FEATURE: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_FEATURE_SEEN); break; default: ASSERT(!"invalid object type", "clustObjectSeen: invalid object type"); break; } psScrCBObjSeen = NULL; psScrCBObjViewer = NULL; } } }
// //////////////////////////////////////////////////////////////////////////// // A remote player has left the game bool MultiPlayerLeave(UDWORD playerIndex) { char buf[255]; if (playerIndex >= MAX_PLAYERS) { ASSERT(false, "Bad player number"); return false; } NETlogEntry("Player leaving game", SYNC_FLAG, playerIndex); debug(LOG_NET,"** Player %u [%s], has left the game at game time %u.", playerIndex, getPlayerName(playerIndex), gameTime); ssprintf(buf, _("%s has Left the Game"), getPlayerName(playerIndex)); if (ingame.localJoiningInProgress) { clearPlayer(playerIndex, false); } else if (NetPlay.isHost) // If hosting, and game has started (not in pre-game lobby screen, that is). { sendPlayerLeft(playerIndex); } game.skDiff[playerIndex] = 0; addConsoleMessage(buf, DEFAULT_JUSTIFY, SYSTEM_MESSAGE); if (NetPlay.players[playerIndex].wzFile.isSending) { char buf[256]; ssprintf(buf, _("File transfer has been aborted for %d.") , playerIndex); addConsoleMessage(buf, DEFAULT_JUSTIFY, SYSTEM_MESSAGE); debug(LOG_INFO, "=== File has been aborted for %d ===", playerIndex); NetPlay.players[playerIndex].wzFile.isSending = false; NetPlay.players[playerIndex].needFile = false; } NetPlay.players[playerIndex].kick = true; // Don't wait for GAME_GAME_TIME messages from them. if (widgGetFromID(psWScreen, IDRET_FORM)) { audio_QueueTrack(ID_CLAN_EXIT); } // fire script callback to reassign skirmish players. CBPlayerLeft = playerIndex; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_PLAYERLEFT); netPlayersUpdated = true; return true; }
// update routine for the cluster system void clusterUpdate(void) { SDWORD i; for(i=1; i< CLUSTER_MAX; i++) { if (aClusterEmpty[i]) { scrCBEmptyClusterID = i; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_CLUSTER_EMPTY); aClusterEmpty[i] = false; } } }
/*! * Preparations before entering the game loop * Would start the timer in an event based mainloop */ static void startGameLoop(void) { SetGameMode(GS_NORMAL); if (!levLoadData(aLevelName, NULL, GTYPE_SCENARIO_START)) { debug( LOG_FATAL, "Shutting down after failure" ); exit(EXIT_FAILURE); } //after data is loaded check the research stats are valid if (!checkResearchStats()) { debug( LOG_FATAL, "Invalid Research Stats" ); debug( LOG_FATAL, "Shutting down after failure" ); exit(EXIT_FAILURE); } //and check the structure stats are valid if (!checkStructureStats()) { debug( LOG_FATAL, "Invalid Structure Stats" ); debug( LOG_FATAL, "Shutting down after failure" ); exit(EXIT_FAILURE); } screen_StopBackDrop(); // Trap the cursor if cursor snapping is enabled if (war_GetTrapCursor()) { wzGrabMouse(); } // set a flag for the trigger/event system to indicate initialisation is complete gameInitialised = true; if (challengeActive) { addMissionTimerInterface(); } if (game.type == SKIRMISH) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL); } screen_disableMapPreview(); }
/* The video playback loop */ void videoLoop() { bool videoFinished; ASSERT(videoMode == 1, "videoMode out of sync"); // display a frame of the FMV videoFinished = !seq_UpdateFullScreenVideo(nullptr); pie_ScreenFlip(CLEAR_BLACK); // should we stop playing? if (videoFinished || keyPressed(KEY_ESC) || mouseReleased(MOUSE_LMB)) { seq_StopFullScreenVideo(); //set the next video off - if any if (videoFinished && seq_AnySeqLeft()) { seq_StartNextFullScreenVideo(); } else { // remove the intelligence screen if necessary if (messageIsImmediate()) { intResetScreen(true); setMessageImmediate(false); } //don't do the callback if we're playing the win/lose video if (!getScriptWinLoseVideo()) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_VIDEO_QUIT); } else if (!bMultiPlayer) { displayGameOver(getScriptWinLoseVideo() == PLAY_WIN, false); } triggerEvent(TRIGGER_VIDEO_QUIT); } } }
/* process the results of a completed research topic */ void researchResult(UDWORD researchIndex, UBYTE player, bool bDisplay, STRUCTURE *psResearchFacility, bool bTrigger) { RESEARCH *pResearch = &asResearch[researchIndex]; MESSAGE *pMessage; //the message gets sent to console char consoleMsg[MAX_RESEARCH_MSG_SIZE]; ASSERT_OR_RETURN(, researchIndex < asResearch.size(), "Invalid research index %u", researchIndex); syncDebug("researchResult(%u, %u, …)", researchIndex, player); MakeResearchCompleted(&asPlayerResList[player][researchIndex]); //check for structures to be made available for (unsigned short pStructureResult : pResearch->pStructureResults) { if (apStructTypeLists[player][pStructureResult] != REDUNDANT) { apStructTypeLists[player][pStructureResult] = AVAILABLE; } } //check for structures to be made redundant for (unsigned short pRedStruct : pResearch->pRedStructs) { apStructTypeLists[player][pRedStruct] = REDUNDANT; } //check for component replacement if (!pResearch->componentReplacement.empty()) { for (auto &ri : pResearch->componentReplacement) { COMPONENT_STATS *pOldComp = ri.pOldComponent; replaceComponent(ri.pNewComponent, pOldComp, player); apCompLists[player][pOldComp->compType][pOldComp->index] = REDUNDANT; } } //check for artefacts to be made available for (auto &componentResult : pResearch->componentResults) { //determine the type of artefact COMPONENT_TYPE type = componentResult->compType; //set the component state to AVAILABLE int compInc = componentResult->index; if (apCompLists[player][type][compInc] != REDUNDANT) { apCompLists[player][type][compInc] = AVAILABLE; } //check for default sensor if (type == COMP_SENSOR && (asSensorStats + compInc)->location == LOC_DEFAULT) { aDefaultSensor[player] = compInc; } //check for default ECM else if (type == COMP_ECM && (asECMStats + compInc)->location == LOC_DEFAULT) { aDefaultECM[player] = compInc; } //check for default Repair else if (type == COMP_REPAIRUNIT && (asRepairStats + compInc)->location == LOC_DEFAULT) { aDefaultRepair[player] = compInc; enableSelfRepair(player); } } //check for artefacts to be made redundant for (auto &pRedArtefact : pResearch->pRedArtefacts) { COMPONENT_TYPE type = pRedArtefact->compType; apCompLists[player][type][pRedArtefact->index] = REDUNDANT; } //Add message to player's list if Major Topic if ((pResearch->techCode == TC_MAJOR) && bDisplay) { //only play sound if major topic if (player == selectedPlayer) { audio_QueueTrack(ID_SOUND_MAJOR_RESEARCH); } //check there is viewdata for the research topic - just don't add message if not! if (pResearch->pViewData != nullptr) { pMessage = addMessage(MSG_RESEARCH, false, player); if (pMessage != nullptr) { pMessage->pViewData = pResearch->pViewData; jsDebugMessageUpdate(); } } } else if (player == selectedPlayer && bDisplay) { audio_QueueTrack(ID_SOUND_RESEARCH_COMPLETED); } if (player == selectedPlayer && bDisplay) { //add console text message if (pResearch->pViewData != nullptr) { snprintf(consoleMsg, MAX_RESEARCH_MSG_SIZE, _("Research completed: %s"), _(pResearch->pViewData->textMsg[0].toUtf8().c_str())); addConsoleMessage(consoleMsg, LEFT_JUSTIFY, SYSTEM_MESSAGE); } else { addConsoleMessage(_("Research Completed"), LEFT_JUSTIFY, SYSTEM_MESSAGE); } } if (psResearchFacility) { psResearchFacility->pFunctionality->researchFacility.psSubject = nullptr; // Make sure topic is cleared } if ((bMultiPlayer || player == selectedPlayer) && bTrigger) { psCBLastResearch = pResearch; // Fun with pointers. Throw them into some random global variable, and get Nexus to absorb them. CBResFacilityOwner = player; psCBLastResStructure = psResearchFacility; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_RESEARCHCOMPLETED); psCBLastResStructure = nullptr; CBResFacilityOwner = -1; psCBLastResearch = nullptr; } triggerEventResearched(pResearch, psResearchFacility, player); }
bool stageThreeInitialise() { STRUCTURE *psStr; UDWORD i; DROID *psDroid; bool fromSave = (getSaveGameType() == GTYPE_SAVE_START || getSaveGameType() == GTYPE_SAVE_MIDMISSION); debug(LOG_WZ, "== stageThreeInitialise =="); loopMissionState = LMS_NORMAL; if (!InitRadar()) // After resLoad cause it needs the game palette initialised. { return false; } // reset the clock to normal speed gameTimeResetMod(); if (!init3DView()) // Initialise 3d view stuff. After resLoad cause it needs the game palette initialised. { return false; } effectResetUpdates(); initLighting(0, 0, mapWidth, mapHeight); pie_InitLighting(); if (fromSave) { // these two lines are the biggest hack in the world. // the reticule seems to get detached from 'reticuleup' // this forces it back in sync... intRemoveReticule(); intAddReticule(); } if (bMultiPlayer) { if (!fromSave) { multiGameInit(); } initTemplates(); } preProcessVisibility(); prepareScripts(getLevelLoadType() == GTYPE_SAVE_MIDMISSION || getLevelLoadType() == GTYPE_SAVE_START); if (!fpathInitialise()) { return false; } mapInit(); gridReset(); //if mission screen is up, close it. if (MissionResUp) { intRemoveMissionResultNoAnim(); } // Re-inititialise some static variables. resizeRadar(); setAllPauseStates(false); /* decide if we have to create teams, ONLY in multiplayer mode!*/ if (bMultiPlayer && alliancesSharedVision(game.alliance)) { createTeamAlliances(); /* Update ally vision for pre-placed structures and droids */ for (i = 0; i < MAX_PLAYERS; i++) { if (i != selectedPlayer) { /* Structures */ for (psStr = apsStructLists[i]; psStr; psStr = psStr->psNext) { if (aiCheckAlliances(psStr->player, selectedPlayer)) { visTilesUpdate((BASE_OBJECT *)psStr); } } /* Droids */ for (psDroid = apsDroidLists[i]; psDroid; psDroid = psDroid->psNext) { if (aiCheckAlliances(psDroid->player, selectedPlayer)) { visTilesUpdate((BASE_OBJECT *)psDroid); } } } } } countUpdate(); if (getLevelLoadType() != GTYPE_SAVE_MIDMISSION) { if (getDebugMappingStatus()) { triggerEventCheatMode(true); } eventFireCallbackTrigger((TRIGGER_TYPE)CALL_GAMEINIT); triggerEvent(TRIGGER_GAME_INIT); } return true; }
/* Manages update of all the active function mappings */ void keyProcessMappings(bool bExclude) { KEY_MAPPING *keyToProcess; bool bMetaKeyDown; SDWORD i; /* Bomb out if there are none */ if (!keyMappings || !numActiveMappings || !bKeyProcessing) { return; } /* Jump out if we've got a new mapping */ (void) checkQwertyKeys(); /* Check for the meta keys */ if (keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL) || keyDown(KEY_LALT) || keyDown(KEY_RALT) || keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT) || keyDown(KEY_LMETA) || keyDown(KEY_RMETA)) { bMetaKeyDown = true; } else { bMetaKeyDown = false; } /* Run through all our mappings */ for (keyToProcess = keyMappings; keyToProcess != NULL; keyToProcess = keyToProcess->psNext) { /* We haven't acted upon it */ if (!keyToProcess->active) { /* Get out if it's inactive */ break; } /* Skip innappropriate ones when necessary */ if (bExclude && keyToProcess->status != KEYMAP_ALWAYS_PROCESS) { break; } if (keyToProcess->subKeyCode == (KEY_CODE)KEY_MAXSCAN) { continue; } if (keyToProcess->function == NULL) { continue; } if (keyToProcess->metaKeyCode == KEY_IGNORE && !bMetaKeyDown && !(keyToProcess->status == KEYMAP__DEBUG && !getDebugMappingStatus())) { switch (keyToProcess->action) { case KEYMAP_PRESSED: /* Were the right keys pressed? */ if (keyPressed(keyToProcess->subKeyCode)) { lastSubKey = keyToProcess->subKeyCode; /* Jump to the associated function call */ keyToProcess->function(); } break; case KEYMAP_DOWN: /* Is the key Down? */ if (keyDown(keyToProcess->subKeyCode)) { lastSubKey = keyToProcess->subKeyCode; /* Jump to the associated function call */ keyToProcess->function(); } break; case KEYMAP_RELEASED: /* Has the key been released? */ if (keyReleased(keyToProcess->subKeyCode)) { lastSubKey = keyToProcess->subKeyCode; /* Jump to the associated function call */ keyToProcess->function(); } break; default: debug(LOG_FATAL, "Unknown key action (action code %u) while processing keymap.", (unsigned int)keyToProcess->action); abort(); break; } } /* Process the combi ones */ if ((keyToProcess->metaKeyCode != KEY_IGNORE && bMetaKeyDown) && !(keyToProcess->status == KEYMAP__DEBUG && !getDebugMappingStatus())) { /* It's a combo keypress - one held down and the other pressed */ if (keyDown(keyToProcess->metaKeyCode) && keyPressed(keyToProcess->subKeyCode)) { lastMetaKey = keyToProcess->metaKeyCode; lastSubKey = keyToProcess->subKeyCode; keyToProcess->function(); } else if (keyToProcess->altMetaKeyCode != KEY_IGNORE) { if (keyDown(keyToProcess->altMetaKeyCode) && keyPressed(keyToProcess->subKeyCode)) { lastMetaKey = keyToProcess->metaKeyCode; lastSubKey = keyToProcess->subKeyCode; keyToProcess->function(); } } } } /* Script callback - find out what meta key was pressed */ cbPressedMetaKey = KEY_IGNORE; /* getLastMetaKey() can't be used here, have to do manually */ if (keyDown(KEY_LCTRL)) { cbPressedMetaKey = KEY_LCTRL; } else if (keyDown(KEY_RCTRL)) { cbPressedMetaKey = KEY_RCTRL; } else if (keyDown(KEY_LALT)) { cbPressedMetaKey = KEY_LALT; } else if (keyDown(KEY_RALT)) { cbPressedMetaKey = KEY_RALT; } else if (keyDown(KEY_LSHIFT)) { cbPressedMetaKey = KEY_LSHIFT; } else if (keyDown(KEY_RSHIFT)) { cbPressedMetaKey = KEY_RSHIFT; } else if (keyDown(KEY_LMETA)) { cbPressedMetaKey = KEY_LMETA; } else if (keyDown(KEY_RMETA)) { cbPressedMetaKey = KEY_RMETA; } /* Find out what keys were pressed */ for (i = 0; i < KEY_MAXSCAN; i++) { /* Skip meta keys */ switch (i) { case KEY_LCTRL: case KEY_RCTRL: case KEY_LALT: case KEY_RALT: case KEY_LSHIFT: case KEY_RSHIFT: case KEY_LMETA: case KEY_RMETA: continue; break; } /* Let scripts process this key if it's pressed */ if (keyPressed((KEY_CODE)i)) { cbPressedKey = i; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_KEY_PRESSED); } } }
// load up the data for a level bool levLoadData(const char* name, char *pSaveName, GAME_TYPE saveType) { LEVEL_DATASET *psNewLevel, *psBaseData, *psChangeLevel; SDWORD i; bool bCamChangeSaveGame; debug(LOG_WZ, "Loading level %s (%s, type %d)", name, pSaveName, (int)saveType); if (saveType == GTYPE_SAVE_START || saveType == GTYPE_SAVE_MIDMISSION) { if (!levReleaseAll()) { debug(LOG_ERROR, "Failed to unload old data"); return false; } } levelLoadType = saveType; // find the level dataset psNewLevel = levFindDataSet(name); if (psNewLevel == NULL) { debug(LOG_WZ, "Dataset %s not found - trying to load as WRF", name); return levLoadSingleWRF(name); } debug(LOG_WZ, "** Data set found is %s type %d", psNewLevel->pName, (int)psNewLevel->type); /* Keep a copy of the present level name */ sstrcpy(currentLevelName, name); bCamChangeSaveGame = false; if (pSaveName && saveType == GTYPE_SAVE_START) { if (psNewLevel->psChange != NULL) { bCamChangeSaveGame = true; debug(LOG_WZ, "** CAMCHANGE FOUND"); } } // select the change dataset if there is one psChangeLevel = NULL; if (((psNewLevel->psChange != NULL) && (psCurrLevel != NULL)) || bCamChangeSaveGame) { //store the level name debug(LOG_WZ, "Found CAMCHANGE dataset"); psChangeLevel = psNewLevel; psNewLevel = psNewLevel->psChange; } // ensure the correct dataset is loaded if (psNewLevel->type == LDS_CAMPAIGN) { debug(LOG_ERROR, "Cannot load a campaign dataset (%s)", psNewLevel->pName); return false; } else { if (psCurrLevel != NULL) { if ((psCurrLevel->psBaseData != psNewLevel->psBaseData) || (psCurrLevel->type < LDS_NONE && psNewLevel->type >= LDS_NONE) || (psCurrLevel->type >= LDS_NONE && psNewLevel->type < LDS_NONE)) { // there is a dataset loaded but it isn't the correct one debug(LOG_WZ, "Incorrect base dataset loaded (%p != %p, %d - %d)", psCurrLevel->psBaseData, psNewLevel->psBaseData, (int)psCurrLevel->type, (int)psNewLevel->type); if (!levReleaseAll()) // this sets psCurrLevel to NULL { return false; } } else { debug(LOG_WZ, "Correct base dataset already loaded."); } } // setup the correct dataset to load if necessary if (psCurrLevel == NULL) { if (psNewLevel->psBaseData != NULL) { debug(LOG_WZ, "Setting base dataset to load: %s", psNewLevel->psBaseData->pName); } psBaseData = psNewLevel->psBaseData; } else { debug(LOG_WZ, "No base dataset to load"); psBaseData = NULL; } } setCurrentMap(psNewLevel->pName, psNewLevel->players); if (!rebuildSearchPath(psNewLevel->dataDir, true)) { return false; } // reset the old mission data if necessary if (psCurrLevel != NULL) { debug(LOG_WZ, "Reseting old mission data"); if (!levReleaseMissionData()) { return false; } } // need to free the current map and droids etc for a save game if ((psBaseData == NULL) && (pSaveName != NULL)) { if (!saveGameReset()) { return false; } } // initialise if necessary if (psNewLevel->type == LDS_COMPLETE || //psNewLevel->type >= LDS_MULTI_TYPE_START || psBaseData != NULL) { debug(LOG_WZ, "Calling stageOneInitialise!"); if (!stageOneInitialise()) { return false; } } // load up a base dataset if necessary if (psBaseData != NULL) { debug(LOG_WZ, "Loading base dataset %s", psBaseData->pName); for(i=0; i<LEVEL_MAXFILES; i++) { if (psBaseData->apDataFiles[i]) { // load the data debug(LOG_WZ, "Loading [directory: %s] %s ...", PHYSFS_getRealDir(psBaseData->apDataFiles[i]), psBaseData->apDataFiles[i]); if (!resLoad(psBaseData->apDataFiles[i], i)) { return false; } } } } if (psNewLevel->type == LDS_CAMCHANGE) { if (!campaignReset()) { return false; } } if (psNewLevel->game == -1) //no .gam file to load - BETWEEN missions (for Editor games only) { ASSERT( psNewLevel->type == LDS_BETWEEN, "levLoadData: only BETWEEN missions do not need a .gam file" ); debug(LOG_WZ, "No .gam file for level: BETWEEN mission"); if (pSaveName != NULL) { if (psBaseData != NULL) { if (!stageTwoInitialise()) { return false; } } //set the mission type before the saveGame data is loaded if (saveType == GTYPE_SAVE_MIDMISSION) { debug(LOG_WZ, "Init mission stuff"); if (!startMissionSave(psNewLevel->type)) { return false; } debug(LOG_NEVER, "dataSetSaveFlag"); dataSetSaveFlag(); } debug(LOG_NEVER, "Loading savegame: %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } } if ((pSaveName == NULL) || (saveType == GTYPE_SAVE_START)) { debug(LOG_NEVER, "Start mission - no .gam"); if (!startMission((LEVEL_TYPE)psNewLevel->type, NULL)) { return false; } } } //we need to load up the save game data here for a camchange if (bCamChangeSaveGame) { if (pSaveName != NULL) { if (psBaseData != NULL) { if (!stageTwoInitialise()) { return false; } } debug(LOG_NEVER, "loading savegame: %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } if (!campaignReset()) { return false; } } } // load the new data debug(LOG_NEVER, "Loading mission dataset: %s", psNewLevel->pName); for(i=0; i < LEVEL_MAXFILES; i++) { if (psNewLevel->game == i) { // do some more initialising if necessary if (psNewLevel->type == LDS_COMPLETE || psNewLevel->type >= LDS_MULTI_TYPE_START || (psBaseData != NULL && !bCamChangeSaveGame)) { if (!stageTwoInitialise()) { return false; } } // load a savegame if there is one - but not if already done so if (pSaveName != NULL && !bCamChangeSaveGame) { //set the mission type before the saveGame data is loaded if (saveType == GTYPE_SAVE_MIDMISSION) { debug(LOG_WZ, "Init mission stuff"); if (!startMissionSave(psNewLevel->type)) { return false; } debug(LOG_NEVER, "dataSetSaveFlag"); dataSetSaveFlag(); } debug(LOG_NEVER, "Loading save game %s", pSaveName); if (!loadGame(pSaveName, false, true,true)) { return false; } } if ((pSaveName == NULL) || (saveType == GTYPE_SAVE_START)) { // load the game debug(LOG_WZ, "Loading scenario file %s", psNewLevel->apDataFiles[i]); switch (psNewLevel->type) { case LDS_COMPLETE: case LDS_CAMSTART: debug(LOG_WZ, "LDS_COMPLETE / LDS_CAMSTART"); if (!startMission(LDS_CAMSTART, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_BETWEEN: debug(LOG_WZ, "LDS_BETWEEN"); if (!startMission(LDS_BETWEEN, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MKEEP: debug(LOG_WZ, "LDS_MKEEP"); if (!startMission(LDS_MKEEP, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_CAMCHANGE: debug(LOG_WZ, "LDS_CAMCHANGE"); if (!startMission(LDS_CAMCHANGE, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_EXPAND: debug(LOG_WZ, "LDS_EXPAND"); if (!startMission(LDS_EXPAND, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_EXPAND_LIMBO: debug(LOG_WZ, "LDS_LIMBO"); if (!startMission(LDS_EXPAND_LIMBO, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MCLEAR: debug(LOG_WZ, "LDS_MCLEAR"); if (!startMission(LDS_MCLEAR, psNewLevel->apDataFiles[i])) { return false; } break; case LDS_MKEEP_LIMBO: debug(LOG_WZ, "LDS_MKEEP_LIMBO"); if (!startMission(LDS_MKEEP_LIMBO, psNewLevel->apDataFiles[i])) { return false; } break; default: ASSERT( psNewLevel->type >= LDS_MULTI_TYPE_START, "levLoadData: Unexpected mission type" ); debug(LOG_WZ, "default (MULTIPLAYER)"); if (!startMission(LDS_CAMSTART, psNewLevel->apDataFiles[i])) { return false; } break; } } } else if (psNewLevel->apDataFiles[i]) { // load the data debug(LOG_WZ, "Loading %s", psNewLevel->apDataFiles[i]); if (!resLoad(psNewLevel->apDataFiles[i], i + CURRENT_DATAID)) { return false; } } } if (pSaveName != NULL) { //load MidMission Extras if (!loadMissionExtras(pSaveName, psNewLevel->type)) { return false; } } if (bMultiPlayer) { loadMultiScripts(); } if (pSaveName != NULL && saveType == GTYPE_SAVE_MIDMISSION) { //load script stuff // load the event system state here for a save game debug(LOG_SAVE, "Loading script system state"); if (!loadScriptState(pSaveName)) { return false; } } if (!stageThreeInitialise()) { return false; } dataClearSaveFlag(); //this enables us to to start cam2/cam3 without going via a save game and get the extra droids //in from the script-controlled Transporters if (!pSaveName && psNewLevel->type == LDS_CAMSTART) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_NO_REINFORCEMENTS_LEFT); } //restore the level name for comparisons on next mission load up if (psChangeLevel == NULL) { psCurrLevel = psNewLevel; } else { psCurrLevel = psChangeLevel; } { // Copy this info to be used by the crash handler for the dump file char buf[256]; ssprintf(buf, "Current Level/map is %s", psCurrLevel->pName); addDumpInfo(buf); } return true; }
/* General housekeeping for the object system */ void objmemUpdate(void) { BASE_OBJECT *psCurr, *psNext, *psPrev; #ifdef DEBUG // do a general validity check first objListIntegCheck(); #endif // tell the script system about any destroyed objects if (psDestroyedObj != NULL) { scrvUpdateBasePointers(); } /* Go through the destroyed objects list looking for objects that were destroyed before this turn */ /* First remove the objects from the start of the list */ while (psDestroyedObj != NULL && psDestroyedObj->died <= gameTime - deltaGameTime) { psNext = psDestroyedObj->psNext; if (!objmemDestroy(psDestroyedObj)) { if (psDestroyedObj->type == OBJ_DROID) { debug(LOG_DEATH, "skipping %p (%s: id %u) this round, will try again later.", psDestroyedObj, ((DROID *)psDestroyedObj)->aName, ((DROID *)psDestroyedObj)->id); return; } } psDestroyedObj = psNext; } /* Now see if there are any further down the list Keep track of the previous object to set its Next pointer*/ for(psCurr = psPrev = psDestroyedObj; psCurr != NULL; psCurr = psNext) { psNext = psCurr->psNext; if (psCurr->died <= gameTime - deltaGameTime) { objmemDestroy(psCurr); /*set the linked list up - you will never be deleting the top of the list, so don't have to check*/ psPrev->psNext = psNext; } else { // do the object died callback psCBObjDestroyed = psCurr; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_OBJ_DESTROYED); switch (psCurr->type) { case OBJ_DROID: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DROID_DESTROYED); break; case OBJ_STRUCTURE: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_STRUCT_DESTROYED); break; case OBJ_FEATURE: eventFireCallbackTrigger((TRIGGER_TYPE)CALL_FEATURE_DESTROYED); break; default: break; } psCBObjDestroyed = NULL; triggerEventDestroyed(psCurr); psPrev = psCurr; } } }
bool stageThreeInitialise(void) { STRUCTURE *psStr; UDWORD i; DROID *psDroid; debug(LOG_WZ, "== stageThreeInitalise =="); bTrackingTransporter = false; loopMissionState = LMS_NORMAL; if(!InitRadar()) // After resLoad cause it needs the game palette initialised. { return false; } // reset the clock to normal speed gameTimeResetMod(); if (!init3DView()) // Initialise 3d view stuff. After resLoad cause it needs the game palette initialised. { return false; } effectResetUpdates(); initLighting(0, 0, mapWidth, mapHeight); if(bMultiPlayer) { // FIXME Is this really needed? debug( LOG_WZ, "multiGameInit()\n" ); multiGameInit(); cmdDroidMultiExpBoost(true); } preProcessVisibility(); // Load any stored templates; these need to be available ASAP initTemplates(); if (!fpathInitialise()) { return false; } mapInit(); clustInitialise(); gridReset(); //if mission screen is up, close it. if(MissionResUp) { intRemoveMissionResultNoAnim(); } // Re-inititialise some static variables. driveInitVars(false); resizeRadar(); setAllPauseStates(false); /* decide if we have to create teams, ONLY in multiplayer mode!*/ if (bMultiPlayer && game.alliance == ALLIANCES_TEAMS) { createTeamAlliances(); /* Update ally vision for pre-placed structures and droids */ for(i=0;i<MAX_PLAYERS;i++) { if(i != selectedPlayer) { /* Structures */ for(psStr=apsStructLists[i]; psStr; psStr=psStr->psNext) { if(aiCheckAlliances(psStr->player,selectedPlayer)) visTilesUpdate((BASE_OBJECT *)psStr); } /* Droids */ for(psDroid=apsDroidLists[i]; psDroid; psDroid=psDroid->psNext) { if(aiCheckAlliances(psDroid->player,selectedPlayer)) visTilesUpdate((BASE_OBJECT *)psDroid); } } } } // ffs JS (and its a global!) if (getLevelLoadType() != GTYPE_SAVE_MIDMISSION) { eventFireCallbackTrigger((TRIGGER_TYPE)CALL_GAMEINIT); triggerEvent(TRIGGER_GAME_INIT); } return true; }
bool msgStackFireTop(void) { SDWORD _callbackType; char msg[255]; if(msgStackPos < 0) { debug(LOG_ERROR, "msgStackFireTop: msgStackPos < 0"); return false; } if(!msgStackGetCallbackType(&_callbackType)) return false; switch(_callbackType) { case CALL_VIDEO_QUIT: debug(LOG_SCRIPT, "msgStackFireTop: popped CALL_VIDEO_QUIT"); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_VIDEO_QUIT); break; case CALL_DORDER_STOP: ASSERT(false,"CALL_DORDER_STOP is currently disabled"); debug(LOG_SCRIPT, "msgStackFireTop: popped CALL_DORDER_STOP"); if(!msgStackGetDroid(&psScrCBOrderDroid)) return false; eventFireCallbackTrigger((TRIGGER_TYPE)CALL_DORDER_STOP); break; case CALL_BEACON: if(!msgStackGetXY(&beaconX, &beaconY)) return false; if(!msgStackGetFrom(&MultiMsgPlayerFrom)) return false; if(!msgStackGetTo(&MultiMsgPlayerTo)) return false; if(!msgStackGetMsg(msg)) return false; strcpy(MultiplayMsg, msg); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_BEACON); break; case CALL_AI_MSG: if(!msgStackGetFrom(&MultiMsgPlayerFrom)) return false; if(!msgStackGetTo(&MultiMsgPlayerTo)) return false; if(!msgStackGetMsg(msg)) return false; strcpy(MultiplayMsg, msg); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_AI_MSG); break; default: debug(LOG_ERROR, "msgStackFireTop: unknown callback type"); return false; break; } if(!msgStackPop()) return false; return true; }