Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}