void CFeature::Initialize(const FeatureLoadParams& params) { def = params.featureDef; udef = params.unitDef; id = params.featureID; team = params.teamID; allyteam = params.allyTeamID; heading = params.heading; buildFacing = params.facing; smokeTime = params.smokeTime; mass = def->mass; health = def->health; maxHealth = def->health; resources = SResourcePack(def->metal, def->energy); crushResistance = def->crushResistance; xsize = ((buildFacing & 1) == 0) ? def->xsize : def->zsize; zsize = ((buildFacing & 1) == 1) ? def->xsize : def->zsize; noSelect = !def->selectable; // by default, any feature that is a dead unit can move // in all dimensions; all others (trees, rocks, ...) can // only move vertically and also do not allow velocity to // build in XZ // (movementMask exists mostly for trees, which depend on // speed for falling animations but should never actually // *move* in XZ, so their velocityMask *does* include XZ) moveCtrl.SetMovementMask(mix(OnesVector, UpVector, udef == nullptr )); moveCtrl.SetVelocityMask(mix(OnesVector, UpVector, udef == nullptr && def->drawType < DRAWTYPE_TREE)); // set position before mid-position Move((params.pos).cClampInMap(), false); // use base-class version, AddFeature() below // will already insert us in the update-queue CWorldObject::SetVelocity(params.speed); switch (def->drawType) { case DRAWTYPE_NONE: { } break; case DRAWTYPE_MODEL: { if ((model = def->LoadModel()) != NULL) { SetMidAndAimPos(model->relMidPos, model->relMidPos, true); SetRadiusAndHeight(model); // only initialize the LM for modelled features // (this is still never animated but allows for // custom piece display-lists, etc) localModel.SetModel(model); } else { LOG_L(L_ERROR, "[%s] couldn't load model for %s", __FUNCTION__, def->name.c_str()); } } break; default: { // always >= DRAWTYPE_TREE here // LoadFeaturesFromMap() doesn't set a scale for trees SetMidAndAimPos(UpVector * TREE_RADIUS, UpVector * TREE_RADIUS, true); SetRadiusAndHeight(TREE_RADIUS, TREE_RADIUS * 2.0f); drawPos = pos; drawMidPos = midPos; } break; } UpdateMidAndAimPos(); UpdateTransformAndPhysState(); collisionVolume = def->collisionVolume; if (collisionVolume.DefaultToSphere()) collisionVolume.InitSphere(radius); if (collisionVolume.DefaultToFootPrint()) collisionVolume.InitBox(float3(xsize * SQUARE_SIZE, height, zsize * SQUARE_SIZE)); // feature does not have an assigned ID yet // this MUST be done before the Block() call featureHandler->AddFeature(this); quadField->AddFeature(this); ChangeTeam(team); UpdateCollidableStateBit(CSolidObject::CSTATE_BIT_SOLIDOBJECTS, def->collidable); Block(); // allow Spring.SetFeatureBlocking to be called from gadget:FeatureCreated // (callin sees the complete default state, but can change any part of it) eventHandler.FeatureCreated(this); eventHandler.RenderFeatureCreated(this); }
void CFeature::Initialize(const float3& _pos, const FeatureDef* _def, short int _heading, int facing, int _team, int _allyteam, const UnitDef* _udef, const float3& speed, int _smokeTime) { def = _def; udef = _udef; defName = def->myName; heading = _heading; buildFacing = facing; team = _team; allyteam = _allyteam; emitSmokeTime = _smokeTime; mass = def->mass; crushResistance = def->crushResistance; health = def->maxHealth; blocking = def->blocking; xsize = ((facing & 1) == 0) ? def->xsize : def->zsize; zsize = ((facing & 1) == 1) ? def->xsize : def->zsize; noSelect = def->noSelect; float fRadius = 1.0f; float fHeight = 0.0f; if (def->drawType == DRAWTYPE_MODEL) { model = def->LoadModel(); if (!model) { LOG_L(L_ERROR, "Features: Couldn't load model for %s", defName.c_str()); } else { relMidPos = model->relMidPos; fRadius = model->radius; fHeight = model->height; // note: gets deleted in ~CSolidObject collisionVolume = new CollisionVolume(def->collisionVolume, fRadius); } } else if (def->drawType >= DRAWTYPE_TREE) { relMidPos = UpVector * TREE_RADIUS; fRadius = TREE_RADIUS; fHeight = fRadius * 2.0f; // LoadFeaturesFromMap() doesn't set a scale for trees // note: gets deleted in ~CSolidObject collisionVolume = new CollisionVolume(def->collisionVolume, fRadius); } Move3D(_pos.ClampInBounds(), false); SetRadiusAndHeight(fRadius, fHeight); UpdateMidPos(); CalculateTransform(); featureHandler->AddFeature(this); qf->AddFeature(this); // maybe should not be here, but it prevents crashes caused by team = -1 ChangeTeam(team); if (blocking) { Block(); } if (def->floating) { finalHeight = ground->GetHeightAboveWater(pos.x, pos.z); } else { finalHeight = ground->GetHeightReal(pos.x, pos.z); } if (speed != ZeroVector) { deathSpeed = speed; } reachedFinalPos = (speed == ZeroVector && pos.y == finalHeight); }
CPieceProjectile::CPieceProjectile(const float3& pos, const float3& speed, LocalModelPiece* lmp, int f, CUnit* owner, float radius): CProjectile(pos, speed, owner, true, false, true), flags(f), dispList(lmp? lmp->dispListID: 0), omp(NULL), spinAngle(0.0f), alphaThreshold(0.1f), oldSmokePos(pos), drawTrail(true), curCallback(0), age(0) { checkCol = false; if (owner) { if ((flags & PF_NoCEGTrail) == 0) { const std::vector<std::string>& pieceCEGs = owner->unitDef->pieceCEGTags; const std::string& cegTag = !pieceCEGs.empty()? pieceCEGs[gs->randInt() % pieceCEGs.size()]: ""; if (!cegTag.empty()) { cegID = gCEG->Load(explGenHandler, cegTag.c_str()); } else { flags |= PF_NoCEGTrail; } } /* If we're an S3O unit, this is where ProjectileHandler fetches our texture from. */ model = owner->model; /* If we're part of an S3O unit, save this so we can draw with the right teamcolour. */ colorTeam = owner->team; // copy the owner's alphaThreshold value alphaThreshold = owner->alphaThreshold; } if (lmp) { omp = lmp->original; } else { omp = NULL; } castShadow = true; if (pos.y - ground->GetApproximateHeight(pos.x, pos.z) > 10) { useAirLos = true; } oldSmokeDir = speed; oldSmokeDir.Normalize(); const float3 camDir = (pos - camera->pos).Normalize(); if (camera->pos.distance(pos) + (1 - fabs(camDir.dot(oldSmokeDir))) * 3000 < 200) { drawTrail = false; } //! neither spinVec nor spinSpeed technically //! needs to be synced, but since instances of //! this class are themselves synced and have //! LuaSynced{Ctrl, Read} exposure we treat //! them that way for consistency spinVec = gs->randVector(); spinVec.Normalize(); spinSpeed = gs->randFloat() * 20; for (int a = 0; a < 8; ++a) { oldInfos[a] = new OldInfo; oldInfos[a]->pos = pos; oldInfos[a]->size = gu->usRandFloat() * 2 + 2; } SetRadiusAndHeight(radius, 0.0f); drawRadius = 32.0f; #ifdef TRACE_SYNC tracefile << "New CPieceProjectile: "; tracefile << pos.x << " " << pos.y << " " << pos.z << " " << speed.x << " " << speed.y << " " << speed.z << "\n"; #endif ph->AddProjectile(this); }