CRepulseGfx::CRepulseGfx(CUnit* owner,CProjectile* repulsed,float maxDist,float3 color) : CProjectile(repulsed?repulsed->pos:float3(0,0,0),repulsed?repulsed->speed:float3(0,0,0),owner, false), repulsed(repulsed), age(0), sqMaxDist(maxDist*maxDist+100), color(color) { if (owner) AddDeathDependence(owner); if (repulsed) AddDeathDependence(repulsed); checkCol=false; useAirLos=true; SetRadius(maxDist); for(int y=0;y<5;++y){ float yp=(y/4.0f-0.5f); for(int x=0;x<5;++x){ float xp=(x/4.0f-0.5f); float d=sqrt(xp*xp+yp*yp); difs[y*5+x]=(1-cos(d*2))*20; } } }
CWeaponProjectile::CWeaponProjectile(const float3& pos,const float3& speed,CUnit* owner, CUnit* target,const float3 &targetPos, WeaponDef *weaponDef,CWeaponProjectile* interceptTarget) : CProjectile(pos,speed,owner), weaponDef(weaponDef), target(target), targetPos(targetPos), startpos(pos), targeted(false), interceptTarget(interceptTarget) { if(target) AddDeathDependence(target); if(interceptTarget){ interceptTarget->targeted=true; AddDeathDependence(interceptTarget); } if(weaponDef->interceptedByShieldType) interceptHandler.AddShieldInterceptableProjectile(this); if(!weaponDef->visuals.modelName.empty()){ S3DOModel* model = modelParser->Load3DO(string("objects3d/")+weaponDef->visuals.modelName,1,0); if(model){ s3domodel=model; if(s3domodel->rootobject3do) modelDispList= model->rootobject3do->displist; else modelDispList= model->rootobjects3o->displist; } } collisionFlags = weaponDef->collisionFlags; }
CWaitCommandsAI::DeathWait::DeathWait(const Command& cmd) : Wait(CMD_WAITCODE_DEATHWAIT) { GML_RECMUTEX_LOCK(sel); // DeathWait const CUnitSet& selUnits = selectedUnits.selectedUnits; if (cmd.params.size() == 1) { const int unitID = (int)cmd.params[0]; if ((unitID < 0) || (static_cast<size_t>(unitID) >= uh->MaxUnits())) { return; } CUnit* unit = uh->units[unitID]; if (unit == NULL) { return; } if (selUnits.find(unit) != selUnits.end()) { return; } deathUnits.insert(unit); } else if (cmd.params.size() == 6) { const float3 pos0(cmd.params[0], cmd.params[1], cmd.params[2]); const float3 pos1(cmd.params[3], cmd.params[4], cmd.params[5]); CUnitSet tmpSet; SelectAreaUnits(pos0, pos1, tmpSet, false); CUnitSet::iterator it; for (it = tmpSet.begin(); it != tmpSet.end(); ++it) { if (selUnits.find(*it) == selUnits.end()) { deathUnits.insert(*it); } } if (deathUnits.empty()) { return; } } else { return; // unknown param config } valid = true; key = GetNewKey(); waitUnits = selUnits; Command waitCmd(CMD_WAIT, cmd.options); waitCmd.params.push_back(code); waitCmd.params.push_back(GetFloatFromKey(key)); selectedUnits.GiveCommand(waitCmd); CUnitSet::iterator it; for (it = waitUnits.begin(); it != waitUnits.end(); ++it) { AddDeathDependence((CObject*)(*it)); } for (it = deathUnits.begin(); it != deathUnits.end(); ++it) { AddDeathDependence((CObject*)(*it)); } return; }
void CAirMoveType::CheckForCollision(void) { if (!collide) return; SyncedFloat3& pos = owner->midPos; SyncedFloat3& forward = owner->frontdir; float3 midTestPos = pos + forward * 121; std::vector<CUnit*> others = qf->GetUnitsExact(midTestPos, 115); float dist = 200; if (lastColWarning) { DeleteDeathDependence(lastColWarning); lastColWarning = 0; lastColWarningType = 0; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner || !(*ui)->unitDef->canfly) continue; SyncedFloat3& op = (*ui)->midPos; float3 dif = op - pos; float3 forwardDif = forward * (forward.dot(dif)); if (forwardDif.SqLength() < dist * dist) { float frontLength = forwardDif.Length(); float3 ortoDif = dif - forwardDif; // note that the radii are multiplied by two since we rely on // aircraft having half-size hitspheres (see unitloader) // // FIXME: with the new collision volumes, is this still true? // // yes: for backward compatibility, aircraft that do not define // their own custom volumes get halved hitspheres by default float minOrtoDif = ((*ui)->radius + owner->radius) * 2 + frontLength * 0.1f + 10; if (ortoDif.SqLength() < minOrtoDif * minOrtoDif) { dist = frontLength; lastColWarning = (*ui); } } } if (lastColWarning) { lastColWarningType = 2; AddDeathDependence(lastColWarning); return; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner) continue; if (((*ui)->midPos - pos).SqLength() < dist * dist) { lastColWarning = *ui; } } if (lastColWarning) { lastColWarningType = 1; AddDeathDependence(lastColWarning); } return; }
void CTAAirMoveType::CheckForCollision(void) { if (!collide) return; SyncedFloat3& pos = owner->midPos; SyncedFloat3 forward = owner->speed; forward.Normalize(); float3 midTestPos = pos + forward * 121; std::vector<CUnit*> others = qf->GetUnitsExact(midTestPos, 115); float dist = 200; if (lastColWarning) { DeleteDeathDependence(lastColWarning); lastColWarning = 0; lastColWarningType = 0; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner || !(*ui)->unitDef->canfly) continue; SyncedFloat3& op = (*ui)->midPos; float3 dif = op - pos; float3 forwardDif = forward * (forward.dot(dif)); if (forwardDif.SqLength() < dist * dist) { float frontLength = forwardDif.Length(); float3 ortoDif = dif - forwardDif; // note: the radius is multiplied by two since we rely on aircraft // having small spheres (see unitloader) float minOrtoDif = ((*ui)->radius + owner->radius) * 2 + frontLength * 0.05f + 5; if (ortoDif.SqLength() < minOrtoDif * minOrtoDif) { dist = frontLength; lastColWarning = (*ui); } } } if (lastColWarning) { lastColWarningType = 2; AddDeathDependence(lastColWarning); return; } for (std::vector<CUnit*>::iterator ui = others.begin(); ui != others.end(); ++ui) { if (*ui == owner) continue; if (((*ui)->midPos - pos).SqLength() < dist * dist) { lastColWarning = *ui; } } if (lastColWarning) { lastColWarningType = 1; AddDeathDependence(lastColWarning); } return; }
CWeaponProjectile::CWeaponProjectile(const float3& pos, const float3& speed, CUnit* owner, CUnit* target, const float3 &targetPos, const WeaponDef* weaponDef, CWeaponProjectile* interceptTarget, int ttl): CProjectile(pos, speed, owner, true, true, false), targeted(false), weaponDef(weaponDef), weaponDefName(weaponDef? weaponDef->name: std::string("")), target(target), targetPos(targetPos), cegTag(weaponDef? weaponDef->cegTag: std::string("")), cegID(-1U), colorTeam(0), startpos(pos), ttl(ttl), bounces(0), keepBouncing(true), interceptTarget(interceptTarget) { projectileType = WEAPON_BASE_PROJECTILE; if (owner) { colorTeam = owner->team; } if (target) { AddDeathDependence(target, DEPENDENCE_WEAPONTARGET); } if (interceptTarget) { interceptTarget->targeted = true; AddDeathDependence(interceptTarget, DEPENDENCE_INTERCEPTTARGET); } assert(weaponDef != NULL); alwaysVisible = weaponDef->visuals.alwaysVisible; ignoreWater = weaponDef->waterweapon; model = weaponDef->LoadModel(); collisionFlags = weaponDef->collisionFlags; ph->AddProjectile(this); ASSERT_SYNCED(id); if (weaponDef->interceptedByShieldType) { // this needs a valid projectile id set assert(id >= 0); interceptHandler.AddShieldInterceptableProjectile(this); } }
CWeaponProjectile::CWeaponProjectile(const float3& pos, const float3& speed, CUnit* owner, CUnit* target, const float3 &targetPos, const WeaponDef* weaponDef, CWeaponProjectile* interceptTarget, bool synced, int ttl): CProjectile(pos, speed, owner, synced, true), weaponDef(weaponDef), weaponDefName(weaponDef? weaponDef->name: std::string("")), target(target), targetPos(targetPos), startpos(pos), targeted(false), interceptTarget(interceptTarget), colorTeam(0), bounces(0), keepBouncing(true), ttl(ttl), cegTag(weaponDef? weaponDef->cegTag: std::string("")) { if (owner) { colorTeam = owner->team; } if (target) { AddDeathDependence(target); } if (interceptTarget) { interceptTarget->targeted = true; AddDeathDependence(interceptTarget); } if (weaponDef) { if(weaponDef->interceptedByShieldType) { interceptHandler.AddShieldInterceptableProjectile(this); } alwaysVisible = weaponDef->visuals.alwaysVisible; if (!weaponDef->visuals.modelName.empty()) { S3DOModel* model = modelParser->Load3DModel(string("objects3d/") + weaponDef->visuals.modelName, 1, colorTeam); if (model) { s3domodel = model; if (s3domodel->rootobject3do) modelDispList = model->rootobject3do->displist; else modelDispList = model->rootobjects3o->displist; } } collisionFlags = weaponDef->collisionFlags; } }
CWaitCommandsAI::SquadWait::SquadWait(const Command& cmd) : Wait(CMD_WAITCODE_SQUADWAIT) { GML_RECMUTEX_LOCK(sel); // SquadWait if (cmd.params.size() != 1) { return; } squadCount = (int)cmd.params[0]; if (squadCount < 2) { return; } const CUnitSet& selUnits = selectedUnits.selectedUnits; CUnitSet::const_iterator it; for (it = selUnits.begin(); it != selUnits.end(); ++it) { CUnit* unit = *it; if (dynamic_cast<CFactory*>(unit)) { buildUnits.insert(unit); } else { waitUnits.insert(unit); } } if (buildUnits.empty() && ((int)waitUnits.size() < squadCount)) { return; } valid = true; key = GetNewKey(); Command waitCmd(CMD_WAIT, cmd.options); waitCmd.params.push_back(code); waitCmd.params.push_back(GetFloatFromKey(key)); SendCommand(waitCmd, buildUnits); SendCommand(waitCmd, waitUnits); for (it = buildUnits.begin(); it != buildUnits.end(); ++it) { AddDeathDependence((CObject*)(*it)); } for (it = waitUnits.begin(); it != waitUnits.end(); ++it) { AddDeathDependence((CObject*)(*it)); } UpdateText(); return; }
void AMoveType::ReservePad(CAirBaseHandler::LandingPad* lp) { AddDeathDependence(lp); reservedPad = lp; padStatus = 0; SetGoal(lp->GetUnit()->pos); }
bool CWeapon::AttackUnit(CUnit *unit,bool userTarget) { if((!userTarget && weaponDef->noAutoTarget)) return false; if(weaponDef->interceptor) return false; weaponPos=owner->pos+owner->frontdir*relWeaponPos.z+owner->updir*relWeaponPos.y+owner->rightdir*relWeaponPos.x; if(weaponPos.y<ground->GetHeight2(weaponPos.x,weaponPos.z)) weaponPos=owner->pos+10; //hope that we are underground because we are a popup weapon and will come above ground later if(!unit) { if(targetType!=Target_Unit) //make the unit be more likely to keep the current target if user start to move it targetType=Target_None; haveUserTarget=false; return false; } float3 targetPos(helper->GetUnitErrorPos(unit,owner->allyteam)); targetPos+=errorVector*(weaponDef->targetMoveError*30*unit->speed.Length()*(1.0-owner->limExperience)); if(!TryTarget(targetPos,userTarget,unit)) return false; if(targetUnit) { DeleteDeathDependence(targetUnit); targetUnit=0; } haveUserTarget=userTarget; targetType=Target_Unit; targetUnit=unit; targetPos=unit->midPos+float3(0,0.3,0)*unit->radius; AddDeathDependence(targetUnit); return true; }
void CTransportUnit::AttachUnit(CUnit* unit, int piece) { DetachUnit(unit); if(unit->inTransport) return; AddDeathDependence(unit); unit->inTransport=true; unit->toBeTransported=false; if (unit->unitDef->stunnedCargo) unit->stunned=true; //make sure unit doesnt fire etc in transport unit->UnBlock(); if(CTAAirMoveType* am=dynamic_cast<CTAAirMoveType*>(moveType)) unit->moveType->useHeading=false; TransportedUnit tu; tu.unit=unit; tu.piece=piece; tu.size=unit->xsize/2; tu.mass=unit->mass; transportCapacityUsed+=tu.size; transportMassUsed+=tu.mass; transported.push_back(tu); unit->CalculateTerrainType(); unit->UpdateTerrainType(); }
void CAirMoveType::SlowUpdate(void) { if(aircraftState!=AIRCRAFT_LANDED && owner->unitDef->maxFuel>0) owner->currentFuel = max (0.f, owner->currentFuel - (16.f/GAME_SPEED)); if(!reservedPad && aircraftState==AIRCRAFT_FLYING && owner->health<owner->maxHealth*repairBelowHealth){ CAirBaseHandler::LandingPad* lp=airBaseHandler->FindAirBase(owner,8000,owner->unitDef->minAirBasePower); if(lp){ AddDeathDependence(lp); reservedPad=lp; padStatus=0; oldGoalPos=goalPos; } } if(owner->pos!=oldSlowUpdatePos){ oldSlowUpdatePos=owner->pos; int newmapSquare=ground->GetSquare(owner->pos); if(newmapSquare!=owner->mapSquare){ owner->mapSquare=newmapSquare; float oldlh=owner->losHeight; float h=owner->pos.y-ground->GetApproximateHeight(owner->pos.x,owner->pos.z); owner->losHeight=h+5; loshandler->MoveUnit(owner,false); if(owner->hasRadarCapacity) radarhandler->MoveUnit(owner); owner->losHeight=oldlh; } qf->MovedUnit(owner); owner->isUnderWater=owner->pos.y+owner->model->height<0; } }
void CAirMoveType::SlowUpdate(void) { if(!reservedPad && aircraftState==AIRCRAFT_FLYING && owner->health<owner->maxHealth*repairBelowHealth){ CAirBaseHandler::LandingPad* lp=airBaseHandler->FindAirBase(owner,8000); if(lp){ AddDeathDependence(lp); reservedPad=lp; padStatus=0; oldGoalPos=goalPos; } } if(owner->pos!=oldSlowUpdatePos){ oldSlowUpdatePos=owner->pos; int newmapSquare=ground->GetSquare(owner->pos); if(newmapSquare!=owner->mapSquare){ owner->mapSquare=newmapSquare; float oldlh=owner->losHeight; float h=owner->pos.y-ground->GetApproximateHeight(owner->pos.x,owner->pos.z); owner->losHeight=h+5; loshandler->MoveUnit(owner,false); if(owner->radarRadius || owner->jammerRadius || owner->sonarRadius) radarhandler->MoveUnit(owner); owner->losHeight=oldlh; } qf->MovedUnit(owner); owner->isUnderWater=owner->pos.y+owner->model->height<0; } }
void CFactory::StartBuild(const UnitDef* buildeeDef) { const float3& buildPos = CalcBuildPos(); const bool blocked = groundBlockingObjectMap->GroundBlocked(buildPos, this); // wait until buildPos is no longer blocked (eg. by a previous buildee) // // it might rarely be the case that a unit got stuck inside the factory // or died right after completion and left some wreckage, but that is up // to players to fix (we no longer broadcast BuggerOff directives, since // those are indiscriminate and ineffective) if (blocked) return; CUnit* b = unitLoader->LoadUnit(buildeeDef, buildPos, team, true, buildFacing, this); if (!unitDef->canBeAssisted) { b->soloBuilder = this; b->AddDeathDependence(this, DEPENDENCE_BUILDER); } AddDeathDependence(b, DEPENDENCE_BUILD); script->StartBuilding(); // set curBuildDef to NULL to indicate construction // has started, otherwise we would keep being called curBuild = b; curBuildDef = NULL; #if (PLAY_SOUNDS == 1) if (losStatus[gu->myAllyTeam] & LOS_INLOS) { Channels::General.PlayRandomSample(unitDef->sounds.build, buildPos); } #endif }
void RepairTask::SetRepairTarget (aiUnit *u) { if (target) DeleteDeathDependence (target); target = u; if (u) AddDeathDependence (u); }
void CSelectedUnits::AddUnit(CUnit* unit) { // if unit is being transported by eg. Hulk or Atlas // then we should not be able to select it if (unit->transporter != NULL && !unit->transporter->unitDef->isFirePlatform) { return; } if (unit->noSelect) { return; } selectedUnits.insert(unit); AddDeathDependence(unit); selectionChanged = true; possibleCommandsChanged = true; if (!(unit->group) || unit->group->id != selectedGroup) selectedGroup = -1; PUSH_CODE_MODE; ENTER_MIXED; unit->commandAI->selected = true; POP_CODE_MODE; }
void CTransportUnit::AttachUnit(CUnit* unit, int piece) { DetachUnit(unit); if (!CanTransport(unit)) return; AddDeathDependence(unit); unit->AddDeathDependence (this); unit->transporter = this; unit->toBeTransported=false; if (!unitDef->isfireplatform) { unit->stunned=true; //make sure unit doesnt fire etc in transport selectedUnits.RemoveUnit(unit); } unit->UnBlock(); loshandler->FreeInstance(unit->los); unit->los=0; if (dynamic_cast<CTAAirMoveType*>(moveType)) { unit->moveType->useHeading=false; } TransportedUnit tu; tu.unit=unit; tu.piece=piece; tu.size=unit->xsize/2; tu.mass=unit->mass; transportCapacityUsed+=tu.size; transportMassUsed+=tu.mass; transported.push_back(tu); unit->CalculateTerrainType(); unit->UpdateTerrainType(); luaCallIns.UnitLoaded(unit, this); }
CRepulseGfx::CRepulseGfx(CUnit* owner, CProjectile* repulsed, float maxDist, const float3& color): CProjectile(repulsed? repulsed->pos: ZeroVector, repulsed? repulsed->speed: ZeroVector, owner, false, false, false), repulsed(repulsed), sqMaxDist((maxDist * maxDist) + 100), age(0), color(color) { if (repulsed) { AddDeathDependence(repulsed); } checkCol = false; useAirLos = true; SetRadius(maxDist); for (int y = 0; y < 5; ++y) { float yp = (y / 4.0f - 0.5f); for (int x = 0; x < 5; ++x) { float xp = (x / 4.0f - 0.5f); float d = 0; if (xp != 0 || yp != 0) { d = fastmath::apxsqrt2(xp * xp + yp * yp); } difs[y * 5 + x] = (1 - fastmath::cos(d * 2)) * 20; } } }
void CSelectedUnits::AddUnit(CUnit* unit) { // if unit is being transported by eg. Hulk or Atlas // then we should not be able to select it CTransportUnit *trans=unit->GetTransporter(); if (trans != NULL && !trans->unitDef->isFirePlatform) { return; } if (unit->noSelect) { return; } GML_RECMUTEX_LOCK(sel); // AddUnit selectedUnits.insert(unit); AddDeathDependence(unit); selectionChanged = true; possibleCommandsChanged = true; if (!(unit->group) || unit->group->id != selectedGroup) selectedGroup = -1; unit->commandAI->selected = true; }
CTorpedoProjectile::CTorpedoProjectile( const float3& pos, const float3& speed, CUnit* owner, float areaOfEffect, float maxSpeed, float tracking, int ttl, CUnit* target, const WeaponDef* weaponDef) : CWeaponProjectile(pos, speed, owner, target, ZeroVector, weaponDef, NULL, ttl), tracking(tracking), maxSpeed(maxSpeed), areaOfEffect(areaOfEffect), target(target), nextBubble(4) { projectileType = WEAPON_TORPEDO_PROJECTILE; curSpeed = speed.Length(); dir = speed / curSpeed; if (target) { AddDeathDependence(target); } SetRadius(0.0f); drawRadius = maxSpeed * 8; // const float3 camDir = (pos - camera->pos).Normalize(); texx = projectileDrawer->torpedotex->xstart - (projectileDrawer->torpedotex->xend - projectileDrawer->torpedotex->xstart) * 0.5f; texy = projectileDrawer->torpedotex->ystart - (projectileDrawer->torpedotex->yend - projectileDrawer->torpedotex->ystart) * 0.5f; #ifdef TRACE_SYNC tracefile << "New projectile: "; tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n"; #endif cegID = gCEG->Load(explGenHandler, cegTag); }
void CPlasmaRepulser::NewProjectile(CWeaponProjectile* p) { if(weaponDef->smartShield && gs->AlliedTeams(p->owner->team,owner->team)) return; float3 dir; if(p->targetPos!=ZeroVector) dir=p->targetPos-p->pos; //assume that it will travel roughly in the direction of the targetpos if it have one else dir=p->speed; //otherwise assume speed will hold constant dir.y=0; dir.Normalize(); float3 dif=owner->pos-p->pos; if(weaponDef->exteriorShield && dif.SqLength() < sqRadius) return; float closeLength=dif.dot(dir); if(closeLength<0) closeLength=0; float3 closeVect=dif-dir*closeLength; if(closeVect.Length2D()<radius*1.5f+400){ incoming.push_back(p); AddDeathDependence(p); } }
CWaitCommandsAI::TimeWait::TimeWait(const Command& cmd, CUnit* _unit) : Wait(CMD_WAITCODE_TIMEWAIT) { if (cmd.params.size() != 1) { return; } valid = true; key = GetNewKey(); unit = _unit; enabled = false; endFrame = 0; duration = GAME_SPEED * (int)cmd.params[0]; factory = (dynamic_cast<CFactory*>(unit) != NULL); Command waitCmd(CMD_WAIT, cmd.options); waitCmd.params.push_back(code); waitCmd.params.push_back(GetFloatFromKey(key)); selectedUnits.ClearSelected(); selectedUnits.AddUnit(unit); selectedUnits.GiveCommand(waitCmd); AddDeathDependence((CObject*)unit); return; }
CLightingProjectile::CLightingProjectile(const float3& pos,const float3& end,CUnit* owner,const float3& color, WeaponDef *weaponDef,int ttl,CWeapon* weap) : CWeaponProjectile(pos,ZeroVector, owner, 0, ZeroVector, weaponDef,0), //CProjectile(pos,ZeroVector,owner), ttl(ttl), color(color), endPos(end), weapon(weap) { checkCol=false; drawRadius=pos.distance(endPos); displacements[0]=0; for(int a=1;a<10;++a) displacements[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f; displacements2[0]=0; for(int a=1;a<10;++a) displacements2[a]=(gs->randFloat()-0.5f)*drawRadius*0.05f; if(weapon) AddDeathDependence(weapon); #ifdef TRACE_SYNC tracefile << "New lighting: "; tracefile << pos.x << " " << pos.y << " " << pos.z << " " << end.x << " " << end.y << " " << end.z << "\n"; #endif }
void CPlasmaRepulser::NewProjectile(CWeaponProjectile* p) { if (weaponDef->smartShield && teamHandler->AlliedTeams(p->owner()->team, owner->team)) { return; } float3 dir = p->speed; if (p->targetPos != ZeroVector) { dir = p->targetPos - p->pos; // assume that it will travel roughly in the direction of the targetpos if it have one } dir.y = 0.0f; dir.SafeNormalize(); const float3 dif = owner->pos - p->pos; if (weaponDef->exteriorShield && (dif.SqLength() < sqRadius)) { return; } const float closeLength = std::max(0.0f, dif.dot(dir)); const float3 closeVect = dif - dir * closeLength; const float closeDist = closeVect.SqLength2D(); // TODO: this isn't good enough in case shield is mounted on a mobile unit, // and this unit moves relatively fast compared to the projectile. // it should probably be: radius + closeLength / |projectile->speed| * |owner->speed|, // but this still doesn't solve anything for e.g. teleporting shields. if (closeDist < Square(radius * 1.5f)) { incomingProjectiles[p->id] = p; AddDeathDependence(p, DEPENDENCE_REPULSED); } }
CWeaponProjectile::CWeaponProjectile(const float3& pos, const float3& speed, CUnit* owner, CUnit* target, const float3 &targetPos, const WeaponDef* weaponDef, CWeaponProjectile* interceptTarget, int ttl): CProjectile(pos, speed, owner, true, true, false), targeted(false), weaponDef(weaponDef), weaponDefName(weaponDef? weaponDef->name: std::string("")), target(target), targetPos(targetPos), cegTag(weaponDef? weaponDef->cegTag: std::string("")), cegID(-1U), colorTeam(0), startpos(pos), ttl(ttl), bounces(0), keepBouncing(true), interceptTarget(interceptTarget) { projectileType = WEAPON_BASE_PROJECTILE; if (owner) { colorTeam = owner->team; } if (target) { AddDeathDependence(target); } if (interceptTarget) { interceptTarget->targeted = true; AddDeathDependence(interceptTarget); } if (weaponDef) { if(weaponDef->interceptedByShieldType) { interceptHandler.AddShieldInterceptableProjectile(this); } alwaysVisible = weaponDef->visuals.alwaysVisible; model = LoadModel(weaponDef); collisionFlags = weaponDef->collisionFlags; } ph->AddProjectile(this); }
void CAirCAI::ExecuteAreaAttack(Command &c) { assert(owner->unitDef->canAttack); AAirMoveType* myPlane = (AAirMoveType*) owner->moveType; if (targetDied) { targetDied = false; inCommand = false; } const float3 pos(c.params[0], c.params[1], c.params[2]); const float radius = c.params[3]; if (inCommand) { if (myPlane->aircraftState == AAirMoveType::AIRCRAFT_LANDED) inCommand = false; if (orderTarget && orderTarget->pos.SqDistance2D(pos) > Square(radius)) { inCommand = false; DeleteDeathDependence(orderTarget); orderTarget = 0; } if (owner->commandShotCount < 0) { if ((c.params.size() == 4) && (commandQue.size() > 1)) { owner->AttackUnit(0, true); FinishCommand(); } else if (owner->userAttackGround) { // reset the attack position after each run float3 attackPos = pos + (gs->randVector() * radius); attackPos.y = ground->GetHeightAboveWater(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); owner->commandShotCount = 0; } } } else { owner->commandShotCount = -1; if (myPlane->aircraftState != AAirMoveType::AIRCRAFT_LANDED) { inCommand = true; std::vector<int> enemyUnitIDs; helper->GetEnemyUnits(pos, radius, owner->allyteam, enemyUnitIDs); if (enemyUnitIDs.empty()) { float3 attackPos = pos + gs->randVector() * radius; attackPos.y = ground->GetHeightAboveWater(attackPos.x, attackPos.z); owner->AttackGround(attackPos, false); } else { // note: the range of randFloat() is inclusive of 1.0f const unsigned int idx(gs->randFloat() * (enemyUnitIDs.size() - 1)); orderTarget = uh->GetUnitUnsafe( enemyUnitIDs[idx] ); owner->AttackUnit(orderTarget, false); AddDeathDependence(orderTarget); } } } }
bool CWeapon::AttackUnit(CUnit* unit, bool userTarget) { if ((!userTarget && weaponDef->noAutoTarget)) return false; if (weaponDef->interceptor) return false; weaponPos = owner->pos + owner->frontdir * relWeaponPos.z + owner->updir * relWeaponPos.y + owner->rightdir * relWeaponPos.x; weaponMuzzlePos = owner->pos + owner->frontdir * relWeaponMuzzlePos.z + owner->updir * relWeaponMuzzlePos.y + owner->rightdir * relWeaponMuzzlePos.x; if (weaponMuzzlePos.y < ground->GetHeightReal(weaponMuzzlePos.x, weaponMuzzlePos.z)) { // hope that we are underground because we are a popup weapon and will come above ground later weaponMuzzlePos = owner->pos + UpVector * 10; } if (!unit) { if (targetType != Target_Unit) { // make the unit be more likely to keep the current target if user starts to move it targetType = Target_None; } haveUserTarget = false; return false; } float3 tempTargetPos = helper->GetUnitErrorPos(unit, owner->allyteam) + errorVector * (weaponDef->targetMoveError * GAME_SPEED * unit->speed.Length() * (1.0f - owner->limExperience)); const float appHeight = ground->GetApproximateHeight(tempTargetPos.x, tempTargetPos.z) + 2.0f; if (tempTargetPos.y < appHeight) tempTargetPos.y = appHeight; if (!TryTarget(tempTargetPos, userTarget, unit)) return false; if (targetUnit) { DeleteDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); targetUnit = NULL; } haveUserTarget = userTarget; targetType = Target_Unit; targetUnit = unit; targetPos = tempTargetPos; AddDeathDependence(targetUnit, DEPENDENCE_TARGETUNIT); avoidTarget = false; return true; }
CCobThread::CCobThread(CCobFile &script, CCobInstance *owner) : owner(owner), script(script) { state = Init; owner->threads.push_back(this); AddDeathDependence(owner); signalMask = 42; }
void CProjectile::Init (const float3& explosionPos, CUnit *owner) { pos += explosionPos; SetRadius(1.7f); ph->AddProjectile(this); if(owner) AddDeathDependence(owner); }
CMissileProjectile::CMissileProjectile(const float3& pos,const float3& speed,CUnit* owner,const DamageArray& damages,float areaOfEffect,float maxSpeed, int ttl,CUnit* target, WeaponDef *weaponDef,float3 targetPos) : CWeaponProjectile(pos,speed,owner,target,ZeroVector,weaponDef,0), damages(damages), ttl(ttl), maxSpeed(maxSpeed), target(target), dir(speed), oldSmoke(pos), age(0), drawTrail(true), numParts(0), areaOfEffect(areaOfEffect), decoyTarget(0), targPos(targetPos), wobbleTime(1), wobbleDir(0,0,0), wobbleDif(0,0,0), isWobbling(weaponDef->wobble>0), extraHeightTime(0) { curSpeed=speed.Length(); dir.Normalize(); oldDir=dir; if(target) AddDeathDependence(target); SetRadius(0.0); if(!weaponDef->visuals.modelName.empty()){ S3DOModel* model = modelParser->Load3DO(string("objects3d/")+weaponDef->visuals.modelName,1,0); if(model){ SetRadius(model->radius); } } drawRadius=radius+maxSpeed*8; ENTER_MIXED; float3 camDir=(pos-camera->pos).Normalize(); if(camera->pos.distance(pos)*0.2+(1-fabs(camDir.dot(dir)))*3000 < 200) drawTrail=false; ENTER_SYNCED; castShadow=true; #ifdef TRACE_SYNC tracefile << "New missile: "; tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n"; #endif if(target) target->IncomingMissile(this); if(weaponDef->trajectoryHeight>0){ float dist=pos.distance(targPos); extraHeight=dist*weaponDef->trajectoryHeight; if(dist<maxSpeed) dist=maxSpeed; extraHeightTime=(int)(dist/*+pos.distance(targPos+UpVector*dist))*0.5*//maxSpeed); extraHeightDecay=extraHeight/extraHeightTime; } }