void CFactory::CreatePlayerUnit(int nType) { PROFILE("CFactory::CreatePlayerUnit(int)"); //static float xPos = 100; //static float yPos = 50; CUnit* unit = new CUnit(nType); // Use default shallow copy since no dynamic info in creation CUnit temp = CGame::GetInstance()->GetUnitInfo(nType); unit->SetAttackPower(temp.GetAttackPower()); unit->SetAttackSpeed(temp.GetAttackSpeed()); unit->SetMaxHP(temp.GetMaxHP()); unit->SetCurrentHP(temp.GetMaxHP()); unit->SetRange(temp.GetRange()); unit->SetSpeed(temp.GetSpeed()); unit->SetState(IDLE); unit->SetDirection(SOUTH_WEST); unit->SetIsPlayerUnit(true); unit->SetAttackSoundID(CGame::GetInstance()->GetAttackSound(unit->GetType())); // Register Events unit->SetDeathSoundID(CGame::GetInstance()->GetDeathSound(unit->GetType())); // Add to manager ObjectManager::GetInstance()->AddObject(unit); // Let it know we aren't hanging on to it unit->Release(); STOP("CFactory::CreatePlayerUnit(int)"); }
/* virtual */ void COrder_Die::Execute(CUnit &unit) { // Show death animation if (AnimateActionDie(unit) == false) { // some units has no death animation unit.Anim.Unbreakable = 0; } if (unit.Anim.Unbreakable) { return ; } const CUnitType &type = *unit.Type; // Die sequence terminated, generate corpse. if (type.CorpseType == NULL) { unit.Remove(NULL); //Wyrmgus start UnitClearOrders(unit); //Wyrmgus end unit.Release(); return ; } const CUnitType &corpseType = *type.CorpseType; Assert(type.TileWidth >= corpseType.TileWidth && type.TileHeight >= corpseType.TileHeight); // Update sight for new corpse // We have to unmark BEFORE changing the type. // Always do that, since types can have different vision properties. //Wyrmgus start // unit.Remove(NULL); MapUnmarkUnitSight(unit); //Wyrmgus end unit.Type = &corpseType; unit.Stats = &corpseType.Stats[unit.Player->Index]; //Wyrmgus start const unsigned int var_size = UnitTypeVar.GetNumberVariable(); std::copy(corpseType.Stats[unit.Player->Index].Variables, corpseType.Stats[unit.Player->Index].Variables + var_size, unit.Variable); //Wyrmgus end UpdateUnitSightRange(unit); //Wyrmgus start // unit.Place(unit.tilePos); MapMarkUnitSight(unit); //Wyrmgus end unit.Frame = 0; UnitUpdateHeading(unit); AnimateActionDie(unit); // with new corpse. }
bool COrder_Build::StartBuilding(CUnit &unit, CUnit &ontop) { const CUnitType &type = this->GetUnitType(); unit.Player->SubUnitType(type); CUnit *build = MakeUnit(const_cast<CUnitType &>(type), unit.Player); // If unable to make unit, stop, and report message if (build == NULL) { // FIXME: Should we retry this? unit.Player->Notify(NotifyYellow, unit.tilePos, _("Unable to create building %s"), type.Name.c_str()); if (unit.Player->AiEnabled) { AiCanNotBuild(unit, type); } return false; } build->Constructed = 1; build->CurrentSightRange = 0; // Building on top of something, may remove what is beneath it if (&ontop != &unit) { CBuildRestrictionOnTop *b; b = static_cast<CBuildRestrictionOnTop *>(OnTopDetails(*build, ontop.Type)); Assert(b); if (b->ReplaceOnBuild) { build->ResourcesHeld = ontop.ResourcesHeld; // We capture the value of what is beneath. build->Variable[GIVERESOURCE_INDEX].Value = ontop.Variable[GIVERESOURCE_INDEX].Value; build->Variable[GIVERESOURCE_INDEX].Max = ontop.Variable[GIVERESOURCE_INDEX].Max; build->Variable[GIVERESOURCE_INDEX].Enable = ontop.Variable[GIVERESOURCE_INDEX].Enable; ontop.Remove(NULL); // Destroy building beneath UnitLost(ontop); UnitClearOrders(ontop); ontop.Release(); } } // Must set action before placing, otherwise it will incorrectly mark radar delete build->CurrentOrder(); build->Orders[0] = COrder::NewActionBuilt(unit, *build); UpdateUnitSightRange(*build); // Must place after previous for map flags build->Place(this->goalPos); // HACK: the building is not ready yet build->Player->UnitTypesCount[type.Slot]--; if (build->Active) { build->Player->UnitTypesAiActiveCount[type.Slot]--; } // We need somebody to work on it. if (!type.BoolFlag[BUILDEROUTSIDE_INDEX].value) { UnitShowAnimation(unit, unit.Type->Animations->Still); unit.Remove(build); this->State = State_BuildFromInside; if (unit.Selected) { SelectedUnitChanged(); } } else { this->State = State_BuildFromOutside; this->BuildingUnit = build; unit.Direction = DirectionToHeading(build->tilePos - unit.tilePos); UnitUpdateHeading(unit); } return true; }
//Wyrmgus start ///* virtual */ int Spell_Summon::Cast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &goalPos) /* virtual */ int Spell_Summon::Cast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &goalPos, int z) //Wyrmgus end { Vec2i pos = goalPos; bool cansummon; CUnitType &unittype = *this->UnitType; int ttl = this->TTL; if (this->RequireCorpse) { const Vec2i offset(1, 1); const Vec2i minPos = pos - offset; const Vec2i maxPos = pos + offset; //Wyrmgus start // CUnit *unit = FindUnit_If(minPos, maxPos, IsDyingAndNotABuilding()); CUnit *unit = FindUnit_If(minPos, maxPos, z, IsDyingAndNotABuilding()); //Wyrmgus end cansummon = false; if (unit != NULL) { // Found a corpse. eliminate it and proceed to summoning. pos = unit->tilePos; //Wyrmgus start z = unit->MapLayer; //Wyrmgus end unit->Remove(NULL); unit->Release(); cansummon = true; } } else { cansummon = true; } if (cansummon) { //Wyrmgus start // DebugPrint("Summoning a %s\n" _C_ unittype.Name.c_str()); DebugPrint("Summoning a %s\n" _C_ unittype.GetDefaultName(*caster.Player).c_str()); //Wyrmgus end // // Create units. // FIXME: do summoned units count on food? // target = MakeUnit(unittype, caster.Player); if (target != NULL) { target->tilePos = pos; //Wyrmgus start target->MapLayer = z; //Wyrmgus end DropOutOnSide(*target, LookingW, NULL); // To avoid defending summoned unit for AI target->Summoned = 1; // // set life span. ttl=0 results in a permanent unit. // if (ttl) { target->TTL = GameCycle + ttl; } // Insert summoned unit to AI force so it will help them in battle if (this->JoinToAiForce && caster.Player->AiEnabled) { int force = caster.Player->Ai->Force.GetForce(caster); if (force != -1) { caster.Player->Ai->Force[force].Insert(*target); target->GroupId = caster.GroupId; CommandDefend(*target, caster, FlushCommands); } } caster.Variable[MANA_INDEX].Value -= spell.ManaCost; } else { DebugPrint("Unable to allocate Unit"); } return 1; } return 0; }
void CFactory::CreateComputerUnit(int nType) { PROFILE("CFactory::CreateComputerUnit(int)"); //static float xPos = 100; //static float yPos = 50; CUnit* unit = new CUnit(nType); // Use default shallow copy since no dynamic info in creation CUnit temp = CGame::GetInstance()->GetCPUUnitInfo(nType); unit->SetAttackPower(temp.GetAttackPower()); unit->SetAttackSpeed(temp.GetAttackSpeed()); unit->SetMaxHP(temp.GetMaxHP()); unit->SetCurrentHP(temp.GetMaxHP()); unit->SetRange(temp.GetRange()); unit->SetSpeed(temp.GetSpeed()); unit->SetState(IDLE); unit->SetDirection(NORTH_WEST); unit->SetIsPlayerUnit(false); // Register Events unit->SetAttackSoundID(CGame::GetInstance()->GetAttackSound(unit->GetType())); unit->SetDeathSoundID(CGame::GetInstance()->GetDeathSound(unit->GetType())); switch(CGame::GetInstance()->GetSelectedCity()->GetID()) { case KCITY1: break; case KCITY2: unit->SetAttackPower(unit->GetAttackPower()+2); break; case KCITY3: unit->SetAttackPower(unit->GetAttackPower()+2); unit->SetAttackSpeed(unit->GetAttackSpeed()-(unit->GetAttackSpeed()*.2f)); unit->SetSpeed(unit->GetSpeed()-(unit->GetSpeed()*.5f)); break; case XCITY1: break; case XCITY2: unit->SetAttackPower(unit->GetAttackPower()+2); break; case XCITY3: unit->SetAttackPower(unit->GetAttackPower()+2); unit->SetAttackSpeed(unit->GetAttackSpeed()-(unit->GetAttackSpeed()*.2f)); unit->SetSpeed(unit->GetSpeed()-(unit->GetSpeed()*.5f)); break; case JCITY1: break; case JCITY2: unit->SetAttackPower(unit->GetAttackPower()+2); break; case JCITY3: unit->SetAttackPower(unit->GetAttackPower()+2); unit->SetAttackSpeed(unit->GetAttackSpeed()-(unit->GetAttackSpeed()*.2f)); unit->SetSpeed(unit->GetSpeed()-(unit->GetSpeed()*.5f)); break; } // Add to manager ObjectManager::GetInstance()->AddObject(unit); // Let it know we aren't hanging on to it unit->Release(); STOP("CFactory::CreateComputerUnit(int)"); }
static void Finish(COrder_Built &order, CUnit &unit) { const CUnitType &type = *unit.Type; CPlayer &player = *unit.Player; DebugPrint("%d: Building %s(%s) ready.\n" _C_ player.Index _C_ type.Ident.c_str() _C_ type.Name.c_str()); // HACK: the building is ready now player.UnitTypesCount[type.Slot]++; if (unit.Active) { player.UnitTypesAiActiveCount[type.Slot]++; } unit.Constructed = 0; if (unit.Frame < 0) { unit.Frame = -1; } else { unit.Frame = 0; } CUnit *worker = order.GetWorkerPtr(); if (worker != NULL) { if (type.BoolFlag[BUILDERLOST_INDEX].value) { // Bye bye worker. LetUnitDie(*worker); worker = NULL; } else { // Drop out the worker. worker->ClearAction(); DropOutOnSide(*worker, LookingW, &unit); // If we can harvest from the new building, do it. if (worker->Type->ResInfo[type.GivesResource]) { CommandResource(*worker, unit, 0); } // If we can reurn goods to a new depot, do it. if (worker->CurrentResource && worker->ResourcesHeld > 0 && type.CanStore[worker->CurrentResource]) { CommandReturnGoods(*worker, &unit, 0); } } } if (type.GivesResource && type.StartingResources != 0) { // Has StartingResources, Use those unit.ResourcesHeld = type.StartingResources; } player.Notify(NotifyGreen, unit.tilePos, _("New %s done"), type.Name.c_str()); if (&player == ThisPlayer) { if (type.MapSound.Ready.Sound) { PlayUnitSound(unit, VoiceReady); } else if (worker) { PlayUnitSound(*worker, VoiceWorkCompleted); } else { PlayUnitSound(unit, VoiceBuilding); } } if (player.AiEnabled) { /* Worker can be NULL */ AiWorkComplete(worker, unit); } // FIXME: Vladi: this is just a hack to test wall fixing, // FIXME: also not sure if the right place... // FIXME: Johns: hardcoded unit-type wall / more races! if (&type == UnitTypeOrcWall || &type == UnitTypeHumanWall) { Map.SetWall(unit.tilePos, &type == UnitTypeHumanWall); unit.Remove(NULL); UnitLost(unit); UnitClearOrders(unit); unit.Release(); return ; } UpdateForNewUnit(unit, 0); // Set the direction of the building if it supports them if (type.NumDirections > 1 && type.BoolFlag[NORANDOMPLACING_INDEX].value == false) { if (type.BoolFlag[WALL_INDEX].value) { // Special logic for walls CorrectWallDirections(unit); CorrectWallNeighBours(unit); } else { unit.Direction = (MyRand() >> 8) & 0xFF; // random heading } UnitUpdateHeading(unit); } if (IsOnlySelected(unit) || &player == ThisPlayer) { SelectedUnitChanged(); } MapUnmarkUnitSight(unit); unit.CurrentSightRange = unit.Stats->Variables[SIGHTRANGE_INDEX].Max; MapMarkUnitSight(unit); order.Finished = true; }
/** ** Cast capture. ** ** @param caster Unit that casts the spell ** @param spell Spell-type pointer ** @param target Target unit that spell is addressed to ** @param goalPos coord of target spot when/if target does not exist ** ** @return =!0 if spell should be repeated, 0 if not */ /* virtual */ int Spell_Capture::Cast(CUnit &caster, const SpellType &spell, CUnit *target, const Vec2i &/*goalPos*/) { if (!target || caster.Player == target->Player) { return 0; } if (this->DamagePercent) { if ((100 * target->Variable[HP_INDEX].Value) / target->Variable[HP_INDEX].Max > this->DamagePercent && target->Variable[HP_INDEX].Value > this->Damage) { HitUnit(&caster, *target, this->Damage); if (this->SacrificeEnable) { // No corpse. caster.Remove(NULL); caster.Release(); } return 1; } } caster.Player->Score += target->Variable[POINTS_INDEX].Value; if (caster.IsEnemy(*target)) { if (target->Type->Building) { caster.Player->TotalRazings++; } else { caster.Player->TotalKills++; } //Wyrmgus start caster.Player->UnitTypeKills[target->Type->Slot]++; /* if (UseHPForXp) { caster.Variable[XP_INDEX].Max += target->Variable[HP_INDEX].Value; } else { caster.Variable[XP_INDEX].Max += target->Variable[POINTS_INDEX].Value; } caster.Variable[XP_INDEX].Value = caster.Variable[XP_INDEX].Max; */ //distribute experience between nearby units belonging to the same player if (!target->Type->BoolFlag[BUILDING_INDEX].value) { std::vector<CUnit *> table; SelectAroundUnit(caster, 6, table, MakeAndPredicate(HasSamePlayerAs(*caster.Player), IsNotBuildingType())); if (UseHPForXp) { caster.Variable[XP_INDEX].Max += target->Variable[HP_INDEX].Value / (table.size() + 1); } else { caster.Variable[XP_INDEX].Max += target->Variable[POINTS_INDEX].Value / (table.size() + 1); } caster.Variable[XP_INDEX].Value = caster.Variable[XP_INDEX].Max; caster.XPChanged(); for (size_t i = 0; i != table.size(); ++i) { if (UseHPForXp) { table[i]->Variable[XP_INDEX].Max += target->Variable[HP_INDEX].Value / (table.size() + 1); } else { table[i]->Variable[XP_INDEX].Max += target->Variable[POINTS_INDEX].Value / (table.size() + 1); } table[i]->Variable[XP_INDEX].Value = table[i]->Variable[XP_INDEX].Max; table[i]->XPChanged(); } } //Wyrmgus end caster.Variable[KILL_INDEX].Value++; caster.Variable[KILL_INDEX].Max++; caster.Variable[KILL_INDEX].Enable = 1; } target->ChangeOwner(*caster.Player); UnitClearOrders(*target); if (this->JoinToAIForce && caster.Player->AiEnabled) { int force = caster.Player->Ai->Force.GetForce(caster); if (force != -1) { caster.Player->Ai->Force[force].Insert(*target); target->GroupId = caster.GroupId; CommandDefend(*target, caster, FlushCommands); } } if (this->SacrificeEnable) { // No corpse. caster.Remove(NULL); caster.Release(); } else { caster.Variable[MANA_INDEX].Value -= spell.ManaCost; } return 0; }