Exemplo n.º 1
0
void AddObjectOld(
	int x, int y, Vec2i size,
	const TOffsetPic * pic, PickupType type, int tileFlags)
{
	TObject *o = CArrayGet(&gObjs, ObjAdd(
		Vec2iNew(x, y), size, NULL, type, tileFlags));
	o->pic = pic;
	o->wreckedPic = NULL;
	o->structure = 0;
	o->flags = 0;
	MapTryMoveTileItem(&gMap, &o->tileItem, Vec2iFull2Real(Vec2iNew(x, y)));
}
Exemplo n.º 2
0
int ObjAdd(
	Vec2i pos, Vec2i size,
	const char *picName, PickupType type, int tileFlags)
{
	// Find an empty slot in actor list
	TObject *o = NULL;
	int i;
	for (i = 0; i < (int)gObjs.size; i++)
	{
		TObject *obj = CArrayGet(&gObjs, i);
		if (!obj->isInUse)
		{
			o = obj;
			break;
		}
	}
	if (o == NULL)
	{
		TObject obj;
		memset(&obj, 0, sizeof obj);
		CArrayPushBack(&gObjs, &obj);
		i = (int)gObjs.size - 1;
		o = CArrayGet(&gObjs, i);
	}
	memset(o, 0, sizeof *o);
	o->pic = NULL;
	o->wreckedPic = NULL;
	o->picName = picName;
	o->Type = type;
	o->structure = 0;
	o->flags = 0;
	o->tileItem.x = o->tileItem.y = -1;
	o->tileItem.flags = tileFlags;
	o->tileItem.kind = KIND_OBJECT;
	o->tileItem.getPicFunc = GetObjectPic;
	o->tileItem.getActorPicsFunc = NULL;
	o->tileItem.w = size.x;
	o->tileItem.h = size.y;
	o->tileItem.id = i;
	MapTryMoveTileItem(&gMap, &o->tileItem, Vec2iFull2Real(pos));
	o->isInUse = true;
	return i;
}
Exemplo n.º 3
0
int MobObjAdd(const Vec2i fullpos, const int player, const int uid)
{
	// Find an empty slot in mobobj list
	TMobileObject *obj = NULL;
	int i;
	for (i = 0; i < (int)gMobObjs.size; i++)
	{
		TMobileObject *m = CArrayGet(&gMobObjs, i);
		if (!m->isInUse)
		{
			obj = m;
			break;
		}
	}
	if (obj == NULL)
	{
		TMobileObject m;
		memset(&m, 0, sizeof m);
		CArrayPushBack(&gMobObjs, &m);
		i = (int)gMobObjs.size - 1;
		obj = CArrayGet(&gMobObjs, i);
	}
	memset(obj, 0, sizeof *obj);
	obj->x = fullpos.x;
	obj->y = fullpos.y;
	obj->player = player;
	obj->uid = uid;
	obj->tileItem.kind = KIND_MOBILEOBJECT;
	obj->tileItem.id = i;
	obj->soundLock = 0;
	obj->isInUse = true;
	obj->tileItem.x = obj->tileItem.y = -1;
	obj->tileItem.getPicFunc = NULL;
	obj->tileItem.getActorPicsFunc = NULL;
	obj->tileItem.drawFunc = (TileItemDrawFunc)BogusDraw;
	obj->tileItem.drawData.MobObjId = i;
	obj->updateFunc = UpdateMobileObject;
	MapTryMoveTileItem(&gMap, &obj->tileItem, Vec2iFull2Real(fullpos));
	return i;
}
Exemplo n.º 4
0
void ObjAdd(const NMapObjectAdd amo)
{
	// Find an empty slot in object list
	TObject *o = NULL;
	int i;
	for (i = 0; i < (int)gObjs.size; i++)
	{
		TObject *obj = CArrayGet(&gObjs, i);
		if (!obj->isInUse)
		{
			o = obj;
			break;
		}
	}
	if (o == NULL)
	{
		TObject obj;
		memset(&obj, 0, sizeof obj);
		CArrayPushBack(&gObjs, &obj);
		i = (int)gObjs.size - 1;
		o = CArrayGet(&gObjs, i);
	}
	memset(o, 0, sizeof *o);
	o->uid = amo.UID;
	o->Class = StrMapObject(amo.MapObjectClass);
	o->Health = amo.Health;
	o->tileItem.x = o->tileItem.y = -1;
	o->tileItem.flags = amo.TileItemFlags;
	o->tileItem.kind = KIND_OBJECT;
	o->tileItem.getPicFunc = GetObjectPic;
	o->tileItem.getActorPicsFunc = NULL;
	o->tileItem.size = o->Class->Size;
	o->tileItem.id = i;
	MapTryMoveTileItem(&gMap, &o->tileItem, Net2Vec2i(amo.Pos));
	o->isInUse = true;
}
Exemplo n.º 5
0
void BulletAdd(const NAddBullet add)
{
	const Vec2i pos = Net2Vec2i(add.MuzzlePos);

	// Find an empty slot in mobobj list
	TMobileObject *obj = NULL;
	int i;
	for (i = 0; i < (int)gMobObjs.size; i++)
	{
		TMobileObject *m = CArrayGet(&gMobObjs, i);
		if (!m->isInUse)
		{
			obj = m;
			break;
		}
	}
	if (obj == NULL)
	{
		TMobileObject m;
		memset(&m, 0, sizeof m);
		CArrayPushBack(&gMobObjs, &m);
		i = (int)gMobObjs.size - 1;
		obj = CArrayGet(&gMobObjs, i);
	}
	memset(obj, 0, sizeof *obj);
	obj->UID = add.UID;
	obj->bulletClass = StrBulletClass(add.BulletClass);
	obj->x = pos.x;
	obj->y = pos.y;
	obj->z = add.MuzzleHeight;
	obj->dz = add.Elevation;

	obj->vel = Vec2iFull2Real(Vec2iScale(
		GetFullVectorsForRadians(add.Angle),
		RAND_INT(obj->bulletClass->SpeedLow, obj->bulletClass->SpeedHigh)));
	if (obj->bulletClass->SpeedScale)
	{
		obj->vel.y = obj->vel.y * TILE_WIDTH / TILE_HEIGHT;
	}

	obj->PlayerUID = add.PlayerUID;
	obj->ActorUID = add.ActorUID;
	obj->range = RAND_INT(
		obj->bulletClass->RangeLow, obj->bulletClass->RangeHigh);

	obj->flags = add.Flags;
	if (obj->bulletClass->HurtAlways)
	{
		obj->flags |= FLAGS_HURTALWAYS;
	}

	obj->tileItem.kind = KIND_MOBILEOBJECT;
	obj->tileItem.id = i;
	obj->isInUse = true;
	obj->tileItem.x = obj->tileItem.y = -1;
	obj->tileItem.getPicFunc = NULL;
	obj->tileItem.getActorPicsFunc = NULL;
	obj->tileItem.drawFunc = NULL;
	obj->tileItem.drawData.MobObjId = i;
	obj->tileItem.CPic = obj->bulletClass->CPic;
	obj->tileItem.CPicFunc = GetBulletDrawContext;
	obj->tileItem.size = obj->bulletClass->Size;
	obj->tileItem.ShadowSize = obj->bulletClass->ShadowSize;
	obj->updateFunc = UpdateBullet;
	MapTryMoveTileItem(&gMap, &obj->tileItem, Vec2iFull2Real(pos));
}
Exemplo n.º 6
0
bool UpdateBullet(TMobileObject *obj, const int ticks)
{
	obj->count += ticks;
	obj->soundLock = MAX(0, obj->soundLock - ticks);
	obj->specialLock = MAX(0, obj->specialLock - ticks);
	if (obj->count < obj->bulletClass->Delay)
	{
		return true;
	}

	if (obj->range >= 0 && obj->count > obj->range)
	{
		if (!gCampaign.IsClient)
		{
			FireGuns(obj, &obj->bulletClass->OutOfRangeGuns);
		}
		return false;
	}

	const Vec2i objPos = Vec2iNew(obj->x, obj->y);

	if (obj->bulletClass->SeekFactor > 0)
	{
		// Find the closest target to this bullet and steer towards it
		const TActor *owner = ActorGetByUID(obj->ActorUID);
		if (owner == NULL)
		{
			return false;
		}
		const TActor *target = AIGetClosestEnemy(objPos, owner, obj->flags);
		if (target && !target->dead)
		{
			for (int i = 0; i < ticks; i++)
			{
				obj->vel = SeekTowards(
					objPos, obj->vel,
					obj->bulletClass->SpeedLow, target->Pos,
					obj->bulletClass->SeekFactor);
			}
		}
	}

	Vec2i pos = Vec2iScale(Vec2iAdd(objPos, obj->vel), ticks);
	HitType hitItem = HIT_NONE;
	if (!gCampaign.IsClient)
	{
		hitItem = HitItem(obj, pos, obj->bulletClass->Persists);
	}
	const Vec2i realPos = Vec2iFull2Real(pos);

	// Falling (grenades)
	if (obj->bulletClass->Falling.GravityFactor != 0)
	{
		bool hasDropped = obj->z <= 0;
		for (int i = 0; i < ticks; i++)
		{
			obj->z += obj->dz;
			if (obj->z <= 0)
			{
				obj->z = 0;
				if (obj->bulletClass->Falling.Bounces)
				{
					obj->dz = -obj->dz / 2;
				}
				else
				{
					obj->dz = 0;
				}
				if (!hasDropped)
				{
					if (!gCampaign.IsClient)
					{
						FireGuns(obj, &obj->bulletClass->Falling.DropGuns);
					}
				}
				hasDropped = true;
				if (obj->bulletClass->Falling.DestroyOnDrop)
				{
					return false;
				}
				SoundPlayAt(
					&gSoundDevice,
					StrSound(obj->bulletClass->HitSound.Wall), realPos);
			}
			else
			{
				obj->dz -= obj->bulletClass->Falling.GravityFactor;
			}
			if (!obj->bulletClass->Falling.FallsDown)
			{
				obj->dz = MAX(0, obj->dz);
			}
		}
	}
	
	// Friction
	const bool isDiagonal = obj->vel.x != 0 && obj->vel.y != 0;
	int frictionComponent = isDiagonal ?
		(int)round(obj->bulletClass->Friction / sqrt(2)) :
		obj->bulletClass->Friction;
	for (int i = 0; i < ticks; i++)
	{
		if (obj->vel.x > 0)
		{
			obj->vel.x -= frictionComponent;
		}
		else if (obj->vel.x < 0)
		{
			obj->vel.x += frictionComponent;
		}

		if (obj->vel.y > 0)
		{
			obj->vel.y -= frictionComponent;
		}
		else if (obj->vel.y < 0)
		{
			obj->vel.y += frictionComponent;
		}
	}

	bool hitWall = false;
	if (!gCampaign.IsClient && hitItem == HIT_NONE)
	{
		hitWall =
			MapIsRealPosIn(&gMap, realPos) && ShootWall(realPos.x, realPos.y);
	}
	if (hitWall || hitItem != HIT_NONE)
	{
		GameEvent b = GameEventNew(GAME_EVENT_BULLET_BOUNCE);
		b.u.BulletBounce.UID = obj->UID;
		if (hitWall && !Vec2iIsZero(obj->vel))
		{
			b.u.BulletBounce.HitType = (int)HIT_WALL;
		}
		else
		{
			b.u.BulletBounce.HitType = (int)hitItem;
		}
		bool alive = true;
		if ((hitWall && !obj->bulletClass->WallBounces) ||
			((hitItem != HIT_NONE) && obj->bulletClass->HitsObjects))
		{
			b.u.BulletBounce.Spark = true;
			CASSERT(!gCampaign.IsClient, "Cannot process bounces as client");
			FireGuns(obj, &obj->bulletClass->HitGuns);
			if (hitWall || !obj->bulletClass->Persists)
			{
				alive = false;
			}
		}
		b.u.BulletBounce.BouncePos = Vec2i2Net(pos);
		b.u.BulletBounce.BounceVel = Vec2i2Net(obj->vel);
		if (hitWall && !Vec2iIsZero(obj->vel))
		{
			// Bouncing
			Vec2i bounceVel = obj->vel;
			pos = GetWallBounceFullPos(objPos, pos, &bounceVel);
			b.u.BulletBounce.BouncePos = Vec2i2Net(pos);
			b.u.BulletBounce.BounceVel = Vec2i2Net(bounceVel);
			obj->vel = bounceVel;
		}
		GameEventsEnqueue(&gGameEvents, b);
		if (!alive)
		{
			return false;
		}
	}
	if (!MapTryMoveTileItem(&gMap, &obj->tileItem, realPos))
	{
		obj->count = obj->range;
		return false;
	}
	obj->x = pos.x;
	obj->y = pos.y;

	if (obj->bulletClass->Erratic)
	{
		for (int i = 0; i < ticks; i++)
		{
			obj->vel.x += ((rand() % 3) - 1) * 128;
			obj->vel.y += ((rand() % 3) - 1) * 128;
		}
	}

	// Proximity function, destroy
	// Only check proximity every now and then
	if (obj->bulletClass->ProximityGuns.size > 0 && !(obj->count & 3))
	{
		if (!gCampaign.IsClient)
		{
			// Detonate the mine if there are characters in the tiles around it
			const Vec2i tv =
				Vec2iToTile(Vec2iFull2Real(pos));
			Vec2i dv;
			for (dv.y = -1; dv.y <= 1; dv.y++)
			{
				for (dv.x = -1; dv.x <= 1; dv.x++)
				{
					const Vec2i dtv = Vec2iAdd(tv, dv);
					if (!MapIsTileIn(&gMap, dtv))
					{
						continue;
					}
					if (TileHasCharacter(MapGetTile(&gMap, dtv)))
					{
						FireGuns(obj, &obj->bulletClass->ProximityGuns);
						return false;
					}
				}
			}
		}
	}

	return true;
}