/** ** Convert unit-type to. ** ** @param player For this player. ** @param src From this unit-type. ** @param dst To this unit-type. */ static void ConvertUnitTypeTo(CPlayer *player, const CUnitType *src, CUnitType *dst) { CUnit *unit; int i; int j; for (i = 0; i < player->TotalNumUnits; ++i) { unit = player->Units[i]; // // Convert already existing units to this type. // if (unit->Type == src) { CommandTransformIntoType(unit, dst); // // Convert trained units to this type. // FIXME: what about buildings? // } else { for (j = 0; j < unit->OrderCount; ++j) { if (unit->Orders[j]->Action == UnitActionTrain && unit->Orders[j]->Type == src) { if (j == 0) { // Must Adjust Ticks to the fraction that was trained unit->Data.Train.Ticks = unit->Data.Train.Ticks * dst->Stats[player->Index].Costs[TimeCost] / src->Stats[player->Index].Costs[TimeCost]; } unit->Orders[j]->Type = dst; } } } } }
/** ** Apply the modifiers of an individual upgrade. ** ** @param unit Unit that will get the modifier applied ** @param um Upgrade modifier that does the effects */ void ApplyIndividualUpgradeModifier(CUnit &unit, const CUpgradeModifier *um) { Assert(um); if (um->Modifier.Variables[SIGHTRANGE_INDEX].Value) { if (!unit.Removed) { MapUnmarkUnitSight(unit); unit.CurrentSightRange = unit.Variable[SIGHTRANGE_INDEX].Value + um->Modifier.Variables[SIGHTRANGE_INDEX].Value; UpdateUnitSightRange(unit); MapMarkUnitSight(unit); } } for (unsigned int j = 0; j < UnitTypeVar.GetNumberVariable(); j++) { unit.Variable[j].Enable |= um->Modifier.Variables[j].Enable; if (um->ModifyPercent[j]) { unit.Variable[j].Value += unit.Variable[j].Value * um->ModifyPercent[j] / 100; unit.Variable[j].Max += unit.Variable[j].Max * um->ModifyPercent[j] / 100; } else { unit.Variable[j].Value += um->Modifier.Variables[j].Value; unit.Variable[j].Increase += um->Modifier.Variables[j].Increase; } unit.Variable[j].Max += um->Modifier.Variables[j].Max; unit.Variable[j].Max = std::max(unit.Variable[j].Max, 0); if (unit.Variable[j].Max > 0) { clamp(&unit.Variable[j].Value, 0, unit.Variable[j].Max); } } if (um->ConvertTo) { CommandTransformIntoType(unit, *um->ConvertTo); } }
/** ** Send command: Unit starts upgrading to. ** ** @param unit pointer to unit. ** @param what pointer to unit-type of the unit upgrade. ** @param flush Flag flush all pending commands. */ void SendCommandTransformInto(CUnit &unit, CUnitType &what, int flush) { if (!IsNetworkGame()) { CommandLog("transform-into", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1); CommandTransformIntoType(unit, what); } else { NetworkSendCommand(MessageCommandUpgrade, unit, 2, 0, NoUnitP, &what, flush); //use X as a way to mark that this is a transformation and not an upgrade } }
/** ** Send command: Building starts upgrading to. ** ** @param unit pointer to unit. ** @param what pointer to unit-type of the unit upgrade. ** @param flush Flag flush all pending commands. */ void SendCommandTransformInto(CUnit &unit, CUnitType &what, int flush) { if (!IsNetworkGame()) { CommandLog("transform-into", &unit, flush, -1, -1, NoUnitP, what.Ident.c_str(), -1); CommandTransformIntoType(unit, what); } else { NetworkSendCommand(MessageCommandTransform, unit, 0, 0, NoUnitP, &what, flush); } }
/** ** Convert unit-type to. ** ** @param player For this player. ** @param src From this unit-type. ** @param dst To this unit-type. */ static void ConvertUnitTypeTo(CPlayer &player, const CUnitType &src, CUnitType &dst) { for (int i = 0; i < player.GetUnitCount(); ++i) { CUnit &unit = player.GetUnit(i); // Convert already existing units to this type. if (unit.Type == &src) { CommandTransformIntoType(unit, dst); // Convert trained units to this type. // FIXME: what about buildings? } else { for (size_t j = 0; j < unit.Orders.size(); ++j) { if (unit.Orders[j]->Action == UnitActionTrain) { COrder_Train &order = *static_cast<COrder_Train *>(unit.Orders[j]); if (&order.GetUnitType() == &src) { order.ConvertUnitType(unit, dst); } } } } } }
/** ** Execute a command (from network). ** ** @param msgnr Network message type ** @param unum Unit number (slot) that receive the command. ** @param x optional X map position. ** @param y optional y map position. ** @param dstnr optional destination unit. */ void ExecCommand(unsigned char msgnr, UnitRef unum, unsigned short x, unsigned short y, UnitRef dstnr) { CUnit &unit = UnitManager.GetSlotUnit(unum); const Vec2i pos(x, y); const int arg1 = x; const int arg2 = y; // // Check if unit is already killed? // if (unit.Destroyed) { DebugPrint(" destroyed unit skipping %d\n" _C_ UnitNumber(unit)); return; } Assert(unit.Type); const int status = (msgnr & 0x80) >> 7; // Note: destroyed destination unit is handled by the action routines. switch (msgnr & 0x7F) { case MessageSync: return; case MessageQuit: return; case MessageChat: return; case MessageCommandStop: CommandLog("stop", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandStopUnit(unit); break; case MessageCommandStand: CommandLog("stand-ground", &unit, status, -1, -1, NoUnitP, NULL, -1); CommandStandGround(unit, status); break; case MessageCommandDefend: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("defend", &unit, status, -1, -1, &dest, NULL, -1); CommandDefend(unit, dest, status); } break; } case MessageCommandFollow: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("follow", &unit, status, -1, -1, &dest, NULL, -1); CommandFollow(unit, dest, status); } break; } case MessageCommandMove: //Wyrmgus start // CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); // CommandMove(unit, pos, status); if (!unit.CanMove()) { //FIXME: find better way to identify whether the unit should move or set a rally point CommandLog("rally-point", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandRallyPoint(unit, pos); } else { CommandLog("move", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandMove(unit, pos, status); } //Wyrmgus end break; //Wyrmgus start case MessageCommandPickUp: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("pick-up", &unit, status, -1, -1, &dest, NULL, -1); CommandPickUp(unit, dest, status); } break; } //Wyrmgus end case MessageCommandRepair: { CUnit *dest = NoUnitP; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("repair", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandRepair(unit, pos, dest, status); break; } case MessageCommandAutoRepair: CommandLog("auto-repair", &unit, status, arg1, arg2, NoUnitP, NULL, 0); CommandAutoRepair(unit, arg1); break; case MessageCommandAttack: { CUnit *dest = NoUnitP; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("attack", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandAttack(unit, pos, dest, status); break; } case MessageCommandGround: CommandLog("attack-ground", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandAttackGround(unit, pos, status); break; //Wyrmgus start case MessageCommandUse: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("use", &unit, status, -1, -1, &dest, NULL, -1); CommandUse(unit, dest, status); } break; } //Wyrmgus end case MessageCommandPatrol: CommandLog("patrol", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandPatrolUnit(unit, pos, status); break; case MessageCommandBoard: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("board", &unit, status, arg1, arg2, &dest, NULL, -1); CommandBoard(unit, dest, status); } break; } case MessageCommandUnload: { CUnit *dest = NULL; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("unload", &unit, status, pos.x, pos.y, dest, NULL, -1); CommandUnload(unit, pos, dest, status); break; } case MessageCommandBuild: CommandLog("build", &unit, status, pos.x, pos.y, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandBuildBuilding(unit, pos, *UnitTypes[dstnr], status); break; case MessageCommandDismiss: CommandLog("dismiss", &unit, FlushCommands, -1, -1, NULL, NULL, -1); CommandDismiss(unit); break; case MessageCommandResourceLoc: CommandLog("resource-loc", &unit, status, pos.x, pos.y, NoUnitP, NULL, -1); CommandResourceLoc(unit, pos, status); break; case MessageCommandResource: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("resource", &unit, status, -1, -1, &dest, NULL, -1); CommandResource(unit, dest, status); } break; } case MessageCommandReturn: { CUnit *dest = (dstnr != (unsigned short)0xFFFF) ? &UnitManager.GetSlotUnit(dstnr) : NULL; CommandLog("return", &unit, status, -1, -1, dest, NULL, -1); CommandReturnGoods(unit, dest, status); break; } case MessageCommandTrain: //Wyrmgus start // CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); // CommandTrainUnit(unit, *UnitTypes[dstnr], status); CommandLog("train", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), arg1); // use X as a way to mark the player CommandTrainUnit(unit, *UnitTypes[dstnr], arg1, status); //Wyrmgus end break; case MessageCommandCancelTrain: // We need (short)x for the last slot -1 if (dstnr != (unsigned short)0xFFFF) { CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), (short)x); CommandCancelTraining(unit, (short)x, UnitTypes[dstnr]); } else { CommandLog("cancel-train", &unit, FlushCommands, -1, -1, NoUnitP, NULL, (short)x); CommandCancelTraining(unit, (short)x, NULL); } break; case MessageCommandUpgrade: //Wyrmgus start /* CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandUpgradeTo(unit, *UnitTypes[dstnr], status); break; */ if (arg1 == 2) { //use X as a way to mark whether this is an upgrade or a transformation CommandLog("transform-into", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandTransformIntoType(unit, *UnitTypes[dstnr]); } else { CommandLog("upgrade-to", &unit, status, -1, -1, NoUnitP, UnitTypes[dstnr]->Ident.c_str(), -1); CommandUpgradeTo(unit, *UnitTypes[dstnr], status); } break; //Wyrmgus end case MessageCommandCancelUpgrade: CommandLog("cancel-upgrade-to", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandCancelUpgradeTo(unit); break; case MessageCommandResearch: CommandLog("research", &unit, status, -1, -1, NoUnitP, AllUpgrades[arg1]->Ident.c_str(), -1); CommandResearch(unit, *AllUpgrades[arg1], status); break; case MessageCommandCancelResearch: CommandLog("cancel-research", &unit, FlushCommands, -1, -1, NoUnitP, NULL, -1); CommandCancelResearch(unit); break; //Wyrmgus start case MessageCommandQuest: { CommandLog("quest", &unit, 0, 0, 0, NoUnitP, Quests[arg1]->Ident.c_str(), -1); CommandQuest(unit, Quests[arg1]); break; } case MessageCommandBuy: { if (dstnr != (unsigned short)0xFFFF) { CUnit &dest = UnitManager.GetSlotUnit(dstnr); Assert(dest.Type); CommandLog("buy", &unit, 0, -1, -1, &dest, NULL, arg1); CommandBuy(unit, &dest, arg1); } break; } //Wyrmgus end default: { int id = (msgnr & 0x7f) - MessageCommandSpellCast; if (arg2 != (unsigned short)0xFFFF) { CUnit *dest = NULL; if (dstnr != (unsigned short)0xFFFF) { dest = &UnitManager.GetSlotUnit(dstnr); Assert(dest && dest->Type); } CommandLog("spell-cast", &unit, status, pos.x, pos.y, dest, NULL, id); CommandSpellCast(unit, pos, dest, *SpellTypeTable[id], status); } else { CommandLog("auto-spell-cast", &unit, status, arg1, -1, NoUnitP, NULL, id); CommandAutoSpellCast(unit, id, arg1); } break; } } }