void recvProcessDebugMappings(NETQUEUE queue) { bool val = false; NETbeginDecode(queue, GAME_DEBUG_MODE); NETbool(&val); NETend(); bool oldDebugMode = getDebugMappingStatus(); processDebugMappings(queue.index, val); bool newDebugMode = getDebugMappingStatus(); char const *cmsg; if (val) { sasprintf((char**)&cmsg, _("%s wants to enable debug mode. Enabled: %s, Disabled: %s."), getPlayerName(queue.index), getWantedDebugMappingStatuses(true).c_str(), getWantedDebugMappingStatuses(false).c_str()); } else { sasprintf((char**)&cmsg, _("%s wants to disable debug mode. Enabled: %s, Disabled: %s."), getPlayerName(queue.index), getWantedDebugMappingStatuses(true).c_str(), getWantedDebugMappingStatuses(false).c_str()); } addConsoleMessage(cmsg, DEFAULT_JUSTIFY, SYSTEM_MESSAGE); if (!oldDebugMode && newDebugMode) { addConsoleMessage(_("Debug mode now enabled!"), DEFAULT_JUSTIFY, SYSTEM_MESSAGE); } else if (oldDebugMode && !newDebugMode) { addConsoleMessage(_("Debug mode now disabled!"), DEFAULT_JUSTIFY, SYSTEM_MESSAGE); } }
bool attemptCheatCode(const char* cheat_name) { const CHEAT_ENTRY * curCheat; static const CHEAT_ENTRY * const EndCheat = &cheatCodes[ARRAY_SIZE(cheatCodes)]; // there is no reason to make people enter "cheat mode" to enter following commands if (!strcasecmp("showfps", cheat_name)) { kf_ToggleFPS(); return true; } else if (!strcasecmp("showlevelname", cheat_name)) { kf_ToggleLevelName(); return true; } if (strcmp(cheat_name, "cheat on") == 0 || strcmp(cheat_name, "debug") == 0) { if (!getDebugMappingStatus()) { kf_ToggleDebugMappings(); } return true; } if (strcmp(cheat_name, "cheat off") == 0 && getDebugMappingStatus()) { kf_ToggleDebugMappings(); return true; } if (!getDebugMappingStatus()) { return false; } for (curCheat = cheatCodes; curCheat != EndCheat; ++curCheat) { if (strcmp(cheat_name, curCheat->pName) == 0) { char buf[256]; /* We've got our man... */ curCheat->function(); // run it // Copy this info to be used by the crash handler for the dump file ssprintf(buf, "User has used cheat code: %s", curCheat->pName); addDumpInfo(buf); /* And get out of here */ Cheated = true; return true; } } return false; }
// process a destroy feature msg. bool recvDestroyFeature(NETQUEUE queue) { FEATURE *pF; uint32_t id; NETbeginDecode(queue, GAME_DEBUG_REMOVE_FEATURE); NETuint32_t(&id); NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to remove feature for player %u.", NetPlay.players[queue.index].position); return false; } pF = IdToFeature(id,ANYPLAYER); if (pF == NULL) { debug(LOG_FEATURE, "feature id %d not found (probably already destroyed)", id); return false; } debug(LOG_FEATURE, "p%d feature id %d destroyed (%s)", pF->player, pF->id, pF->psStats->pName); // Remove the feature locally turnOffMultiMsg(true); destroyFeature(pF, gameTime - deltaGameTime + 1); // deltaGameTime is actually 0 here, since we're between updates. However, the value of gameTime - deltaGameTime + 1 will not change when we start the next tick. turnOffMultiMsg(false); return true; }
// //////////////////////////////////////////////////////////////////////////// // acknowledge the destruction of a structure, from another player. bool recvDestroyStructure(NETQUEUE queue) { uint32_t structID; STRUCTURE *psStruct; NETbeginDecode(queue, GAME_DEBUG_REMOVE_STRUCTURE); NETuint32_t(&structID); NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to remove structure for player %u.", NetPlay.players[queue.index].position); return false; } // Struct to destory psStruct = IdToStruct(structID, ANYPLAYER); if (psStruct) { turnOffMultiMsg(true); // Remove the struct from remote players machine destroyStruct(psStruct, gameTime - deltaGameTime + 1); // deltaGameTime is actually 0 here, since we're between updates. However, the value of gameTime - deltaGameTime + 1 will not change when we start the next tick. turnOffMultiMsg(false); // NOTE: I do not think this should be here! technologyGiveAway(psStruct); } return true; }
void recvMultiPlayerFeature(NETQUEUE queue) { uint32_t ref = 0xff, x = 0, y = 0, id = 0; unsigned int i; NETbeginDecode(queue, GAME_DEBUG_ADD_FEATURE); { NETuint32_t(&ref); NETuint32_t(&x); NETuint32_t(&y); NETuint32_t(&id); } NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to add feature for player %u.", NetPlay.players[queue.index].position); return; } // Find the feature stats list that contains the feature type we want to build for (i = 0; i < numFeatureStats; ++i) { // If we found the correct feature type if (asFeatureStats[i].ref == ref) { // Create a feature of the specified type at the given location FEATURE *result = buildFeature(&asFeatureStats[i], x, y, false); result->id = id; break; } } }
// recv a research topic that is now complete. static bool recvResearch(NETQUEUE queue) { uint8_t player; uint32_t index; int i; PLAYER_RESEARCH *pPlayerRes; NETbeginDecode(queue, GAME_DEBUG_FINISH_RESEARCH); NETuint8_t(&player); NETuint32_t(&index); NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to finish research for player %u.", NetPlay.players[queue.index].position); return false; } syncDebug("player%d, index%u", player, index); if (player >= MAX_PLAYERS || index >= asResearch.size()) { debug(LOG_ERROR, "Bad GAME_DEBUG_FINISH_RESEARCH received, player is %d, index is %u", (int)player, index); return false; } pPlayerRes = &asPlayerResList[player][index]; syncDebug("research status = %d", pPlayerRes->ResearchStatus & RESBITS); if (!IsResearchCompleted(pPlayerRes)) { MakeResearchCompleted(pPlayerRes); researchResult(index, player, false, NULL, true); } // Update allies research accordingly if (game.type == SKIRMISH) { for (i = 0; i < MAX_PLAYERS; i++) { if (alliances[i][player] == ALLIANCE_FORMED) { pPlayerRes = &asPlayerResList[i][index]; if (!IsResearchCompleted(pPlayerRes)) { // Do the research for that player MakeResearchCompleted(pPlayerRes); researchResult(index, i, false, NULL, true); } } } } return true; }
// //////////////////////////////////////////////////////////////////////////// // Accept a droid which was destroyed on another machine bool recvDestroyDroid(NETQUEUE queue) { DROID* psDroid; NETbeginDecode(queue, GAME_DEBUG_REMOVE_DROID); { uint32_t id; // Retrieve the droid NETuint32_t(&id); psDroid = IdToDroid(id, ANYPLAYER); if (!psDroid) { debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?", id, queue.index ); return false; } } NETend(); if (!getDebugMappingStatus()) { debug(LOG_WARNING, "Failed to remove droid for player %u.", NetPlay.players[queue.index].position); return false; } // If the droid has not died on our machine yet, destroy it if(!psDroid->died) { turnOffMultiMsg(true); debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index); destroyDroid(psDroid, gameTime); turnOffMultiMsg(false); } else { debug(LOG_DEATH, "droid %d is confirmed dead by player %d.", psDroid->id, queue.index); } return true; }
// //////////////////////////////////////////////////////////////////////////// // Accept a droid which was destroyed on another machine bool recvDestroyDroid(NETQUEUE queue) { DROID *psDroid; NETbeginDecode(queue, GAME_DEBUG_REMOVE_DROID); { uint32_t id; // Retrieve the droid NETuint32_t(&id); psDroid = IdToDroid(id, ANYPLAYER); if (!psDroid) { debug(LOG_DEATH, "droid %d on request from player %d can't be found? Must be dead already?", id, queue.index); return false; } } NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to remove droid for player %u.", NetPlay.players[queue.index].position); return false; } // If the droid has not died on our machine yet, destroy it if (!psDroid->died) { turnOffMultiMsg(true); debug(LOG_DEATH, "Killing droid %d on request from player %d - huh?", psDroid->id, queue.index); destroyDroid(psDroid, gameTime - deltaGameTime + 1); // deltaGameTime is actually 0 here, since we're between updates. However, the value of gameTime - deltaGameTime + 1 will not change when we start the next tick. turnOffMultiMsg(false); } else { debug(LOG_DEATH, "droid %d is confirmed dead by player %d.", psDroid->id, queue.index); } return true; }
// //////////////////////////////////////////////////////////////////////////// // receive droid creation information from other players bool recvDroid(NETQUEUE queue) { DROID_TEMPLATE t, *pT = &t; DROID *psDroid; uint8_t player; uint32_t id; Position pos; bool haveInitialOrders; INITIAL_DROID_ORDERS initialOrders; NETbeginDecode(queue, GAME_DEBUG_ADD_DROID); { int32_t droidType; NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETqstring(pT->name); pT->id = pT->name; NETint32_t(&droidType); NETuint8_t(&pT->asParts[COMP_BODY]); NETuint8_t(&pT->asParts[COMP_BRAIN]); NETuint8_t(&pT->asParts[COMP_PROPULSION]); NETuint8_t(&pT->asParts[COMP_REPAIRUNIT]); NETuint8_t(&pT->asParts[COMP_ECM]); NETuint8_t(&pT->asParts[COMP_SENSOR]); NETuint8_t(&pT->asParts[COMP_CONSTRUCT]); NETint8_t(&pT->numWeaps); for (int i = 0; i < pT->numWeaps; i++) { NETuint8_t(&pT->asWeaps[i]); } NETbool(&haveInitialOrders); if (haveInitialOrders) { NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } pT->droidType = (DROID_TYPE)droidType; } NETend(); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to add droid for player %u.", NetPlay.players[queue.index].position); return false; } ASSERT_OR_RETURN(false, player < MAX_PLAYERS, "invalid player %u", player); debug(LOG_LIFE, "<=== getting Droid from %u id of %u ", player, id); if ((pos.x == 0 && pos.y == 0) || pos.x > world_coord(mapWidth) || pos.y > world_coord(mapHeight)) { debug(LOG_ERROR, "Received bad droid position (%d, %d) from %d about p%d (%s)", (int)pos.x, (int)pos.y, queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); return false; } // Create that droid on this machine. psDroid = reallyBuildDroid(pT, pos, player, false); // If we were able to build the droid set it up if (psDroid) { psDroid->id = id; addDroid(psDroid, apsDroidLists); if (haveInitialOrders) { psDroid->secondaryOrder = initialOrders.secondaryOrder; psDroid->secondaryOrderPending = psDroid->secondaryOrder; orderDroidLoc(psDroid, DORDER_MOVE, initialOrders.moveToX, initialOrders.moveToY, ModeImmediate); cbNewDroid(IdToStruct(initialOrders.factoryId, ANYPLAYER), psDroid); } syncDebugDroid(psDroid, '+'); } else { debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); #ifdef DEBUG CONPRINTF(ConsoleString, (ConsoleString, "MULTIPLAYER: Couldn't build a remote droid, relying on checking to resync")); #endif return false; } return true; }
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) { /* Bomb out if there are none */ if (keyMappings.empty()) { return; } /* Jump out if we've got a new mapping */ (void) checkQwertyKeys(); /* Check for the meta keys */ bool bMetaKeyDown = keyDown(KEY_LCTRL) || keyDown(KEY_RCTRL) || keyDown(KEY_LALT) || keyDown(KEY_RALT) || keyDown(KEY_LSHIFT) || keyDown(KEY_RSHIFT) || keyDown(KEY_LMETA) || keyDown(KEY_RMETA); /* Run through all our mappings */ for (auto keyToProcess = keyMappings.begin(); keyToProcess != keyMappings.end(); ++keyToProcess) { /* Skip inappropriate ones when necessary */ if (bExclude && keyToProcess->status != KEYMAP_ALWAYS_PROCESS) { break; } if (keyToProcess->subKeyCode == (KEY_CODE)KEY_MAXSCAN) { continue; } if (keyToProcess->function == nullptr) { 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 */ int pressedMetaKey = KEY_IGNORE; /* getLastMetaKey() can't be used here, have to do manually */ if (keyDown(KEY_LCTRL)) { pressedMetaKey = KEY_LCTRL; } else if (keyDown(KEY_RCTRL)) { pressedMetaKey = KEY_RCTRL; } else if (keyDown(KEY_LALT)) { pressedMetaKey = KEY_LALT; } else if (keyDown(KEY_RALT)) { pressedMetaKey = KEY_RALT; } else if (keyDown(KEY_LSHIFT)) { pressedMetaKey = KEY_LSHIFT; } else if (keyDown(KEY_RSHIFT)) { pressedMetaKey = KEY_RSHIFT; } else if (keyDown(KEY_LMETA)) { pressedMetaKey = KEY_LMETA; } else if (keyDown(KEY_RMETA)) { pressedMetaKey = KEY_RMETA; } /* Find out what keys were pressed */ for (int 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)) { triggerEventKeyPressed(pressedMetaKey, i); } } }
/* 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); } } }
static void displayMultiPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, PIELIGHT *pColours) { char str[128]; UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; UDWORD player = psWidget->UserData; //get the in game player number. Position position; Vector3i rotation; if( responsibleFor(player,0) ) { displayExtraGubbins(widgGetFromID(psWScreen,MULTIMENU_FORM)->height); } iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_TEXT_BRIGHT); if(isHumanPlayer(player) || (game.type == SKIRMISH && player<game.maxPlayers) ) { ssprintf(str, "%d: %s", NetPlay.players[player].position, getPlayerName(player)); if (isHumanPlayer(player)) { SetPlayerTextColor(alliances[selectedPlayer][player], player); } else { SetPlayerTextColor(alliances[selectedPlayer][player], player); } while(iV_GetTextWidth(str) >= (MULTIMENU_C0-MULTIMENU_C2-10) ) { str[strlen(str)-1]='\0'; } iV_DrawText(str, x+MULTIMENU_C2, y+MULTIMENU_FONT_OSET); //c3-7 alliance //manage buttons by showing or hiding them. gifts only in campaign, { if(game.alliance != NO_ALLIANCES) { if(alliances[selectedPlayer][player] == ALLIANCE_FORMED) { if(player != selectedPlayer && !giftsUp[player] ) { if (game.alliance != ALLIANCES_TEAMS) { widgReveal(psWScreen,MULTIMENU_GIFT_RAD+ player); widgReveal(psWScreen,MULTIMENU_GIFT_RES+ player); } widgReveal(psWScreen,MULTIMENU_GIFT_DRO+ player); widgReveal(psWScreen,MULTIMENU_GIFT_POW+ player); giftsUp[player] = true; } } else { if(player != selectedPlayer && giftsUp[player]) { if (game.alliance != ALLIANCES_TEAMS) { widgHide(psWScreen,MULTIMENU_GIFT_RAD+ player); widgHide(psWScreen,MULTIMENU_GIFT_RES+ player); } widgHide(psWScreen,MULTIMENU_GIFT_DRO+ player); widgHide(psWScreen,MULTIMENU_GIFT_POW+ player); giftsUp[player] = false; } } } } } if(isHumanPlayer(player)) { SetPlayerTextColor(alliances[selectedPlayer][player], player); // Let's use the real score for MP games if (NetPlay.bComms) { //c8:score, if (Cheated) { sprintf(str,"(cheated)"); } else { sprintf(str,"%d",getMultiStats(player).recentScore); } iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); //c9:kills, sprintf(str,"%d",getMultiStats(player).recentKills); iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); } else { // estimate of score for skirmish games sprintf(str,"%d",ingame.skScores[player][0]); iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); // estimated kills sprintf(str,"%d",ingame.skScores[player][1]); iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); } if(!getDebugMappingStatus()) { //only show player's units, and nobody elses. //c10:units if (myResponsibility(player)) { SetPlayerTextColor(alliances[selectedPlayer][player], player); sprintf(str, "%d", getNumDroids(player) + getNumTransporterDroids(player)); iV_DrawText(str, x+MULTIMENU_C10, y+MULTIMENU_FONT_OSET); } if (runningMultiplayer()) { //c11:ping if (player != selectedPlayer) { if (ingame.PingTimes[player] >= 2000) { sprintf(str,"???"); } else { sprintf(str, "%d", ingame.PingTimes[player]); } iV_DrawText(str, x+MULTIMENU_C11, y+MULTIMENU_FONT_OSET); } } else { int num; STRUCTURE *temp; // NOTE, This tallys up *all* the structures you have. Test out via 'start with no base'. for (num = 0, temp = apsStructLists[player]; temp != NULL;num++,temp = temp->psNext); //c11: Structures sprintf(str, "%d", num); iV_DrawText(str, x+MULTIMENU_C11, y+MULTIMENU_FONT_OSET); } } } else { SetPlayerTextColor(alliances[selectedPlayer][player], player); // Let's use the real score for MP games if (NetPlay.bComms) { //c8:score, if (Cheated) { sprintf(str,"(cheated)"); } else { sprintf(str,"%d",getMultiStats(player).recentScore); } iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); //c9:kills, sprintf(str,"%d",getMultiStats(player).recentKills); iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); } else { // estimate of score for skirmish games sprintf(str,"%d",ingame.skScores[player][0]); iV_DrawText(str, x+MULTIMENU_C8, y+MULTIMENU_FONT_OSET); // estimated kills sprintf(str,"%d",ingame.skScores[player][1]); iV_DrawText(str, x+MULTIMENU_C9, y+MULTIMENU_FONT_OSET); } } /* Display player power instead of number of played games * and number of units instead of ping when in debug mode */ if(getDebugMappingStatus()) //Won't pass this when in both release and multiplayer modes { //c10: Total number of player units in possession sprintf(str,"%d",getNumDroids(player) + getNumTransporterDroids(player)); iV_DrawText(str, x+MULTIMENU_C10, y+MULTIMENU_FONT_OSET); //c11: Player power sprintf(str, "%u", (int)getPower(player)); iV_DrawText(str, MULTIMENU_FORM_X+MULTIMENU_C11, y+MULTIMENU_FONT_OSET); } // a droid of theirs. if(apsDroidLists[player]) { pie_SetGeometricOffset( MULTIMENU_FORM_X+MULTIMENU_C1 ,y+MULTIMENU_PLAYER_H); rotation.x = -15; rotation.y = 45; rotation.z = 0; position.x = 0; position.y = 0; position.z = 2000; //scale them! displayComponentButtonObject(apsDroidLists[player],&rotation,&position,false, 100); } // clean up widgets if player leaves while menu is up. if(!isHumanPlayer(player) && !(game.type == SKIRMISH && player<game.maxPlayers)) { if(widgGetFromID(psWScreen,MULTIMENU_CHANNEL+player)) { widgDelete(psWScreen,MULTIMENU_CHANNEL+ player); } if(widgGetFromID(psWScreen,MULTIMENU_ALLIANCE_BASE+player) ) { widgDelete(psWScreen,MULTIMENU_ALLIANCE_BASE+ player); widgDelete(psWScreen,MULTIMENU_GIFT_RAD+ player); widgDelete(psWScreen,MULTIMENU_GIFT_RES+ player); widgDelete(psWScreen,MULTIMENU_GIFT_DRO+ player); widgDelete(psWScreen,MULTIMENU_GIFT_POW+ player); giftsUp[player] = false; } } }
static void displayExtraGubbins(UDWORD height) { char str[128]; //draw grid iV_Line(MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X , MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, MULTIMENU_FORM_X+MULTIMENU_FORM_W, MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, WZCOL_BLACK); iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_TEXT_BRIGHT); // main wz text color // draw timer getAsciiTime(str, gameTime); iV_DrawText(str, MULTIMENU_FORM_X+MULTIMENU_C2, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET) ; // draw titles. iV_DrawText(_("Alliances"), MULTIMENU_FORM_X+MULTIMENU_C0, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Score"), MULTIMENU_FORM_X+MULTIMENU_C8, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Kills"), MULTIMENU_FORM_X+MULTIMENU_C9, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); if(getDebugMappingStatus()) { // shows # units for *all* players in debug mode ONLY! iV_DrawText(_("Units"), MULTIMENU_FORM_X+MULTIMENU_C10, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Power"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } else { // shows # units for *yourself* (+ team member?) only. iV_DrawText(_("Units"), MULTIMENU_FORM_X+MULTIMENU_C10, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); // ping is useless for non MP games, so display something useful depending on mode. if (runningMultiplayer()) { iV_DrawText(_("Ping"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } else { iV_DrawText(_("Structs"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } } #ifdef DEBUG { unsigned int width; sprintf(str,"Traf: %u/%u", NETgetBytesSent(), NETgetBytesRecvd()); width = iV_GetTextWidth(str); iV_DrawText(str, MULTIMENU_FORM_X, MULTIMENU_FORM_Y + MULTIMENU_FORM_H); sprintf(str,"Pack: %u/%u", NETgetPacketsSent(), NETgetPacketsRecvd()); iV_DrawText(str, MULTIMENU_FORM_X + 20 + width, MULTIMENU_FORM_Y + MULTIMENU_FORM_H); } #endif return; }
// //////////////////////////////////////////////////////////////////////////// bool recvBuildFinished(NETQUEUE queue) { uint32_t structId; STRUCTURE *psStruct; Position pos; uint32_t type, typeindex; uint8_t player; NETbeginDecode(queue, GAME_DEBUG_ADD_STRUCTURE); NETuint32_t(&structId); // get the struct id. NETuint32_t(&type); // Kind of building. NETPosition(&pos); // pos NETuint8_t(&player); NETend(); ASSERT_OR_RETURN(false, player < MAX_PLAYERS, "invalid player %u", player); if (!getDebugMappingStatus() && bMultiPlayer) { debug(LOG_WARNING, "Failed to add structure for player %u.", NetPlay.players[queue.index].position); return false; } psStruct = IdToStruct(structId, ANYPLAYER); if (psStruct) { // make it complete. psStruct->currentBuildPts = psStruct->pStructureType->buildPoints + 1; if (psStruct->status != SS_BUILT) { debug(LOG_SYNC, "Synch error, structure %u was not complete, and should have been.", structId); psStruct->status = SS_BUILT; buildingComplete(psStruct); } debug(LOG_SYNC, "Created normal building %u for player %u", psStruct->id, player); return true; } // The building wasn't started, so we'll have to just plonk it down in the map. // Find the structures stats for (typeindex = 0; typeindex < numStructureStats && asStructureStats[typeindex].ref != type; typeindex++) {} // Find structure target // Check for similar buildings, to avoid overlaps if (TileHasStructure(mapTile(map_coord(pos.x), map_coord(pos.y)))) { // Get the current structure psStruct = getTileStructure(map_coord(pos.x), map_coord(pos.y)); if (asStructureStats[typeindex].type == psStruct->pStructureType->type) { // Correct type, correct location, just rename the id's to sync it.. (urgh) psStruct->id = structId; psStruct->status = SS_BUILT; buildingComplete(psStruct); debug(LOG_SYNC, "Created modified building %u for player %u", psStruct->id, player); #if defined (DEBUG) NETlogEntry("structure id modified", SYNC_FLAG, player); #endif return true; } } // Build the structure psStruct = buildStructure(&(asStructureStats[typeindex]), pos.x, pos.y, player, true); if (psStruct) { psStruct->id = structId; psStruct->status = SS_BUILT; buildingComplete(psStruct); debug(LOG_SYNC, "Huge synch error, forced to create building %u for player %u", psStruct->id, player); #if defined (DEBUG) NETlogEntry("had to plonk down a building", SYNC_FLAG, player); #endif triggerEventStructBuilt(psStruct, NULL); } else { debug(LOG_SYNC, "Gigantic synch error, unable to create building for player %u", player); NETlogEntry("had to plonk down a building, BUT FAILED!", SYNC_FLAG, player); } return false; }
bool canGiveOrdersFor(int player, int playerInQuestion) { return playerInQuestion >= 0 && playerInQuestion < MAX_PLAYERS && (player == playerInQuestion || responsibleFor(player, playerInQuestion) || getDebugMappingStatus()); }
static void displayExtraGubbins(UDWORD height) { char str[128]; //draw grid iV_Line(MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C0 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C8 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C9 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C10 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y, MULTIMENU_FORM_X+MULTIMENU_C11 -6 , MULTIMENU_FORM_Y+height, WZCOL_BLACK); iV_Line(MULTIMENU_FORM_X , MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, MULTIMENU_FORM_X+MULTIMENU_FORM_W, MULTIMENU_FORM_Y+MULTIMENU_PLAYER_H, WZCOL_BLACK); iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_TEXT_BRIGHT); // main wz text color // draw timer getAsciiTime(str, gameTime); iV_DrawText(str, MULTIMENU_FORM_X+MULTIMENU_C2, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET) ; // draw titles. iV_DrawText(_("Alliances"), MULTIMENU_FORM_X+MULTIMENU_C0, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Score"), MULTIMENU_FORM_X+MULTIMENU_C8, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Kills"), MULTIMENU_FORM_X+MULTIMENU_C9, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); iV_DrawText(_("Units"), MULTIMENU_FORM_X+MULTIMENU_C10, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); if (getDebugMappingStatus()) { iV_DrawText(_("Power"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } else { // ping is useless for non MP games, so display something useful depending on mode. if (runningMultiplayer()) { iV_DrawText(_("Ping"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } else { iV_DrawText(_("Structs"), MULTIMENU_FORM_X+MULTIMENU_C11, MULTIMENU_FORM_Y+MULTIMENU_FONT_OSET); } } #ifdef DEBUG iV_SetFont(font_small); for (unsigned q = 0; q < 2; ++q) { unsigned xPos = 0; unsigned yPos = q*12; bool isTotal = q != 0; char const *srText[2] = {_("Sent/Received per sec —"), _("Total Sent/Received —")}; sprintf(str, srText[q]); iV_DrawText(str, MULTIMENU_FORM_X + xPos, MULTIMENU_FORM_Y + height + yPos); xPos += iV_GetTextWidth(str) + 20; sprintf(str, _("Traf: %u/%u"), NETgetStatistic(NetStatisticRawBytes, true, isTotal), NETgetStatistic(NetStatisticRawBytes, false, isTotal)); iV_DrawText(str, MULTIMENU_FORM_X + xPos, MULTIMENU_FORM_Y + height + yPos); xPos += iV_GetTextWidth(str) + 20; sprintf(str, _("Uncompressed: %u/%u"), NETgetStatistic(NetStatisticUncompressedBytes, true, isTotal), NETgetStatistic(NetStatisticUncompressedBytes, false, isTotal)); iV_DrawText(str, MULTIMENU_FORM_X + xPos, MULTIMENU_FORM_Y + height + yPos); xPos += iV_GetTextWidth(str) + 20; sprintf(str, _("Pack: %u/%u"), NETgetStatistic(NetStatisticPackets, true, isTotal), NETgetStatistic(NetStatisticPackets, false, isTotal)); iV_DrawText(str, MULTIMENU_FORM_X + xPos, MULTIMENU_FORM_Y + height + yPos); } #endif return; }
// //////////////////////////////////////////////////////////////////////////// // receive droid creation information from other players bool recvDroid(NETQUEUE queue) { DROID_TEMPLATE* pT; DROID* psDroid; uint8_t player; uint32_t id; Position pos; uint32_t templateID; bool haveInitialOrders; INITIAL_DROID_ORDERS initialOrders; NETbeginDecode(queue, GAME_DEBUG_ADD_DROID); { NETuint8_t(&player); NETuint32_t(&id); NETPosition(&pos); NETuint32_t(&templateID); NETbool(&haveInitialOrders); if (haveInitialOrders) { NETuint32_t(&initialOrders.secondaryOrder); NETint32_t(&initialOrders.moveToX); NETint32_t(&initialOrders.moveToY); NETuint32_t(&initialOrders.factoryId); // For making scripts happy. } pT = IdToTemplate(templateID, player); } NETend(); if (!getDebugMappingStatus()) { debug(LOG_WARNING, "Failed to add droid for player %u.", NetPlay.players[queue.index].position); return false; } ASSERT_OR_RETURN(false, player < MAX_PLAYERS, "invalid player %u", player); debug(LOG_LIFE, "<=== getting Droid from %u id of %u ",player,id); if ((pos.x == 0 && pos.y == 0) || pos.x > world_coord(mapWidth) || pos.y > world_coord(mapHeight)) { debug(LOG_ERROR, "Received bad droid position (%d, %d) from %d about p%d (%s)", (int)pos.x, (int)pos.y, queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); return false; } // If we can not find the template ask for the entire droid instead if (!pT) { debug(LOG_ERROR, "Packet from %d refers to non-existent template %u, [%s : p%d]", queue.index, templateID, isHumanPlayer(player) ? "Human" : "AI", player); return false; } // Create that droid on this machine. psDroid = reallyBuildDroid(pT, pos, player, false); // If we were able to build the droid set it up if (psDroid) { psDroid->id = id; addDroid(psDroid, apsDroidLists); if (haveInitialOrders) { psDroid->secondaryOrder = initialOrders.secondaryOrder; psDroid->secondaryOrderPending = psDroid->secondaryOrder; orderDroidLoc(psDroid, DORDER_MOVE, initialOrders.moveToX, initialOrders.moveToY, ModeImmediate); cbNewDroid(IdToStruct(initialOrders.factoryId, ANYPLAYER), psDroid); } syncDebugDroid(psDroid, '+'); } else { debug(LOG_ERROR, "Packet from %d cannot create droid for p%d (%s)!", queue.index, player, isHumanPlayer(player) ? "Human" : "AI"); #ifdef DEBUG CONPRINTF(ConsoleString, (ConsoleString, "MULTIPLAYER: Couldn't build a remote droid, relying on checking to resync")); #endif return false; } return true; }
bool stageThreeInitialise(void) { STRUCTURE *psStr; UDWORD i; DROID *psDroid; debug(LOG_WZ, "== stageThreeInitalise =="); 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(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(); prepareScripts(getLevelLoadType() == GTYPE_SAVE_MIDMISSION || getLevelLoadType() == GTYPE_SAVE_START); 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 && 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); } } } } if (getLevelLoadType() != GTYPE_SAVE_MIDMISSION) { if (getDebugMappingStatus()) triggerEventCheatMode(true); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_GAMEINIT); triggerEvent(TRIGGER_GAME_INIT); } return true; }
static void displayMultiPlayer(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset) { char str[128]; int x = xOffset + psWidget->x(); int y = yOffset + psWidget->y(); unsigned player = psWidget->UserData; // Get the in game player number. if (responsibleFor(player, 0)) { displayExtraGubbins(widgGetFromID(psWScreen,MULTIMENU_FORM)->height()); } iV_SetFont(font_regular); // font iV_SetTextColour(WZCOL_TEXT_BRIGHT); const bool isHuman = isHumanPlayer(player); const bool isAlly = aiCheckAlliances(selectedPlayer, player); const bool isSelectedPlayer = player == selectedPlayer; SetPlayerTextColor(alliances[selectedPlayer][player], player); if (isHuman || (game.type == SKIRMISH && player<game.maxPlayers) ) { ssprintf(str, "%d: %s", NetPlay.players[player].position, getPlayerName(player)); while (iV_GetTextWidth(str) >= MULTIMENU_C0 - MULTIMENU_C2 - 10) { str[strlen(str) - 1] = '\0'; } iV_DrawText(str, x + MULTIMENU_C2, y + MULTIMENU_FONT_OSET); //c3-7 alliance //manage buttons by showing or hiding them. gifts only in campaign, if (alliancesCanGiveAnything(game.alliance)) { if (isAlly && !isSelectedPlayer && !giftsUp[player] ) { if (alliancesCanGiveResearchAndRadar(game.alliance)) { widgReveal(psWScreen, MULTIMENU_GIFT_RAD + player); widgReveal(psWScreen, MULTIMENU_GIFT_RES + player); } widgReveal(psWScreen, MULTIMENU_GIFT_DRO + player); widgReveal(psWScreen, MULTIMENU_GIFT_POW + player); giftsUp[player] = true; } else if (!isAlly && !isSelectedPlayer && giftsUp[player]) { if (alliancesCanGiveResearchAndRadar(game.alliance)) { widgHide(psWScreen, MULTIMENU_GIFT_RAD + player); widgHide(psWScreen, MULTIMENU_GIFT_RES + player); } widgHide(psWScreen, MULTIMENU_GIFT_DRO + player); widgHide(psWScreen, MULTIMENU_GIFT_POW + player); giftsUp[player] = false; } } } // Let's use the real score for MP games if (NetPlay.bComms) { //c8:score, if (Cheated) { sprintf(str, "(cheated)"); } else { sprintf(str, "%d", getMultiStats(player).recentScore); } iV_DrawText(str, x + MULTIMENU_C8, y + MULTIMENU_FONT_OSET); //c9:kills, sprintf(str, "%d", getMultiStats(player).recentKills); iV_DrawText(str, x + MULTIMENU_C9, y + MULTIMENU_FONT_OSET); } else { // estimate of score for skirmish games sprintf(str, "%d", ingame.skScores[player][0]); iV_DrawText(str, x + MULTIMENU_C8, y + MULTIMENU_FONT_OSET); // estimated kills sprintf(str, "%d", ingame.skScores[player][1]); iV_DrawText(str, x + MULTIMENU_C9, y + MULTIMENU_FONT_OSET); } //only show player's and allies' unit counts, and nobody elses. //c10:units if (isAlly || getDebugMappingStatus()) { sprintf(str, "%d", getNumDroids(player) + getNumTransporterDroids(player)); iV_DrawText(str, x + MULTIMENU_C10, y + MULTIMENU_FONT_OSET); } /* Display player power instead of number of played games * and number of units instead of ping when in debug mode */ if (getDebugMappingStatus()) //Won't pass this when in both release and multiplayer modes { //c11: Player power sprintf(str, "%u", (int)getPower(player)); iV_DrawText(str, MULTIMENU_FORM_X + MULTIMENU_C11, y + MULTIMENU_FONT_OSET); } else if (runningMultiplayer()) { //c11:ping if (!isSelectedPlayer && isHuman) { if (ingame.PingTimes[player] < PING_LIMIT) { sprintf(str, "%03d", ingame.PingTimes[player]); } else { sprintf(str, "∞"); } iV_DrawText(str, x + MULTIMENU_C11, y + MULTIMENU_FONT_OSET); } } else { //c11: Structures if (isAlly || getDebugMappingStatus()) { // NOTE, This tallys up *all* the structures you have. Test out via 'start with no base'. int num = 0; for (STRUCTURE *temp = apsStructLists[player]; temp != NULL; temp = temp->psNext) { ++num; } sprintf(str, "%d", num); iV_DrawText(str, x + MULTIMENU_C11, y + MULTIMENU_FONT_OSET); } } // a droid of theirs. DROID *displayDroid = apsDroidLists[player]; while (displayDroid != NULL && !displayDroid->visible[selectedPlayer]) { displayDroid = displayDroid->psNext; } if (displayDroid) { pie_SetGeometricOffset( MULTIMENU_FORM_X+MULTIMENU_C1 ,y+MULTIMENU_PLAYER_H); Vector3i rotation(-15, 45, 0); Position position(0, 0, BUTTON_DEPTH); // Scale them. if (displayDroid->droidType == DROID_SUPERTRANSPORTER) { position.z = 7850; } else if (displayDroid->droidType == DROID_TRANSPORTER) { position.z = 4100; } displayComponentButtonObject(displayDroid, &rotation, &position, false, 100); } else if (apsDroidLists[player]) { // Show that they have droids, but not which droids, since we can't see them. iV_DrawImageTc(IntImages, IMAGE_GENERIC_TANK, IMAGE_GENERIC_TANK_TC, MULTIMENU_FORM_X + MULTIMENU_C1 - iV_GetImageWidth(IntImages, IMAGE_GENERIC_TANK)/2, y + MULTIMENU_PLAYER_H - iV_GetImageHeight(IntImages, IMAGE_GENERIC_TANK), pal_GetTeamColour(getPlayerColour(player))); } // clean up widgets if player leaves while menu is up. if (!isHuman && !(game.type == SKIRMISH && player < game.maxPlayers)) { if (widgGetFromID(psWScreen, MULTIMENU_CHANNEL + player) != NULL) { widgDelete(psWScreen, MULTIMENU_CHANNEL + player); } if (widgGetFromID(psWScreen, MULTIMENU_ALLIANCE_BASE + player) != NULL) { widgDelete(psWScreen, MULTIMENU_ALLIANCE_BASE + player); widgDelete(psWScreen, MULTIMENU_GIFT_RAD + player); widgDelete(psWScreen, MULTIMENU_GIFT_RES + player); widgDelete(psWScreen, MULTIMENU_GIFT_DRO + player); widgDelete(psWScreen, MULTIMENU_GIFT_POW + player); giftsUp[player] = false; } } }