Beispiel #1
0
static bool TryPlacePickup(HealthPickups *h)
{
	Vec2i size = Vec2iNew(HEALTH_W, HEALTH_H);
	// Attempt to place one in unexplored area
	for (int i = 0; i < 100; i++)
	{
		const Vec2i v = MapGenerateFreePosition(h->map, size);
		if (!Vec2iIsZero(v) && !MapGetTile(h->map, Vec2iToTile(v))->isVisited)
		{
			MapPlaceHealth(v);
			return true;
		}
	}
	// Attempt to place one in out-of-sight area
	for (int i = 0; i < 100; i++)
	{
		const Vec2i v = MapGenerateFreePosition(h->map, size);
		const Vec2i fullpos = Vec2iReal2Full(v);
		const TActor *closestPlayer = AIGetClosestPlayer(fullpos);
		if (!Vec2iIsZero(v) &&
			(!closestPlayer || CHEBYSHEV_DISTANCE(
			fullpos.x, fullpos.y,
			closestPlayer->Pos.x, closestPlayer->Pos.y) >= 256 * 150))
		{
			MapPlaceHealth(v);
			return true;
		}
	}
	// Attempt to place one anyway
	for (int i = 0; i < 100; i++)
	{
		const Vec2i v = MapGenerateFreePosition(h->map, size);
		if (!Vec2iIsZero(v))
		{
			MapPlaceHealth(v);
			return true;
		}
	}
	return false;
}
static void HandleGameEvent(
	GameEvent *e,
	HUD *hud,
	ScreenShake *shake,
	HealthPickups *hp,
	EventHandlers *eventHandlers)
{
	switch (e->Type)
	{
		case GAME_EVENT_SCORE:
			Score(&gPlayerDatas[e->u.Score.PlayerIndex], e->u.Score.Score);
			HUDAddScoreUpdate(hud, e->u.Score.PlayerIndex, e->u.Score.Score);
			break;
		case GAME_EVENT_SOUND_AT:
			if (e->u.SoundAt.Sound)
			{
				SoundPlayAt(
					&gSoundDevice, e->u.SoundAt.Sound, e->u.SoundAt.Pos);
			}
			break;
		case GAME_EVENT_SCREEN_SHAKE:
			*shake = ScreenShakeAdd(
				*shake, e->u.ShakeAmount, gConfig.Graphics.ShakeMultiplier);
			break;
		case GAME_EVENT_SET_MESSAGE:
			HUDDisplayMessage(
				hud, e->u.SetMessage.Message, e->u.SetMessage.Ticks);
			break;
		case GAME_EVENT_GAME_START:
			if (eventHandlers->netInput.channel.state ==
				CHANNEL_STATE_CONNECTED)
			{
				NetInputSendMsg(
					&eventHandlers->netInput, SERVER_MSG_GAME_START);
			}
			break;
		case GAME_EVENT_ADD_HEALTH_PICKUP:
			MapPlaceHealth(e->u.AddPos);
			break;
		case GAME_EVENT_TAKE_HEALTH_PICKUP:
			if (IsPlayerAlive(e->u.PickupPlayer))
			{
				TActor *player = CArrayGet(
					&gActors, gPlayerIds[e->u.PickupPlayer]);
				ActorHeal(player, HEALTH_PICKUP_HEAL_AMOUNT);
				HealthPickupsRemoveOne(hp);
				HUDAddHealthUpdate(
					hud, e->u.PickupPlayer, HEALTH_PICKUP_HEAL_AMOUNT);
			}
			break;
		case GAME_EVENT_MOBILE_OBJECT_REMOVE:
			MobObjDestroy(e->u.MobileObjectRemoveId);
			break;
		case GAME_EVENT_ADD_BULLET:
			BulletAdd(
				e->u.AddBullet.Bullet,
				e->u.AddBullet.MuzzlePos, e->u.AddBullet.MuzzleHeight,
				e->u.AddBullet.Angle, e->u.AddBullet.Direction,
				e->u.AddBullet.Flags, e->u.AddBullet.PlayerIndex);
			break;
		case GAME_EVENT_ADD_MUZZLE_FLASH:
			AddMuzzleFlash(
				e->u.AddMuzzleFlash.FullPos,
				e->u.AddMuzzleFlash.MuzzleHeight,
				e->u.AddMuzzleFlash.Sprites,
				e->u.AddMuzzleFlash.Direction,
				e->u.AddMuzzleFlash.Color,
				e->u.AddMuzzleFlash.Duration);
			break;
		case GAME_EVENT_ADD_FIREBALL:
			AddFireball(e->u.AddFireball);
			break;
		case GAME_EVENT_HIT_CHARACTER:
			HitCharacter(
				e->u.HitCharacter.Flags,
				e->u.HitCharacter.PlayerIndex,
				CArrayGet(&gActors, e->u.HitCharacter.TargetId),
				e->u.HitCharacter.Special,
				e->u.HitCharacter.HasHitSound);
			break;
		case GAME_EVENT_ACTOR_IMPULSE:
			{
				TActor *a = CArrayGet(&gActors, e->u.ActorImpulse.Id);
				a->Vel = Vec2iAdd(a->Vel, e->u.ActorImpulse.Vel);
			}
			break;
		case GAME_EVENT_DAMAGE_CHARACTER:
			DamageCharacter(
				e->u.DamageCharacter.Power,
				e->u.DamageCharacter.PlayerIndex,
				CArrayGet(&gActors, e->u.DamageCharacter.TargetId));
			if (e->u.DamageCharacter.Power != 0)
			{
				HUDAddHealthUpdate(
					hud,
					e->u.DamageCharacter.TargetPlayerIndex,
					-e->u.DamageCharacter.Power);
			}
			break;
		case GAME_EVENT_TRIGGER:
			{
				const Tile *t = MapGetTile(&gMap, e->u.Trigger.TilePos);
				for (int i = 0; i < (int)t->triggers.size; i++)
				{
					Trigger **tp = CArrayGet(&t->triggers, i);
					if ((*tp)->id == e->u.Trigger.Id)
					{
						TriggerActivate(*tp, &gMap.triggers);
						break;
					}
				}
			}
			break;
		case GAME_EVENT_UPDATE_OBJECTIVE:
			{
				struct Objective *o = CArrayGet(
					&gMission.Objectives, e->u.UpdateObjective.ObjectiveIndex);
				o->done += e->u.UpdateObjective.Update;
				MissionObjective *mo = CArrayGet(
					&gMission.missionData->Objectives,
					e->u.UpdateObjective.ObjectiveIndex);
				switch (mo->Type)
				{
				case OBJECTIVE_COLLECT:
					{
						GameEvent e1;
						e1.Type = GAME_EVENT_SCORE;
						e1.u.Score.PlayerIndex =
							e->u.UpdateObjective.PlayerIndex;
						e1.u.Score.Score = PICKUP_SCORE;
						HandleGameEvent(&e1, hud, shake, hp, eventHandlers);
					}
					break;
				case OBJECTIVE_DESTROY:
					{
						GameEvent e1;
						e1.Type = GAME_EVENT_SCORE;
						e1.u.Score.PlayerIndex =
							e->u.UpdateObjective.PlayerIndex;
						e1.u.Score.Score = OBJECT_SCORE;
						HandleGameEvent(&e1, hud, shake, hp, eventHandlers);
					}
					break;
				default:
					// No other special objective handling
					break;
				}
				// Display a text update effect for the objective
				HUDAddObjectiveUpdate(
					hud,
					e->u.UpdateObjective.ObjectiveIndex,
					e->u.UpdateObjective.Update);
				MissionSetMessageIfComplete(&gMission);
			}
			break;
		case GAME_EVENT_MISSION_COMPLETE:
			HUDDisplayMessage(hud, "Mission complete", -1);
			hud->showExit = true;
			MapShowExitArea(&gMap);
			break;
		case GAME_EVENT_MISSION_INCOMPLETE:
			gMission.state = MISSION_STATE_PLAY;
			break;
		case GAME_EVENT_MISSION_PICKUP:
			gMission.state = MISSION_STATE_PICKUP;
			gMission.pickupTime = gMission.time;
			SoundPlay(&gSoundDevice, StrSound("whistle"));
			break;
		case GAME_EVENT_MISSION_END:
			gMission.isDone = true;
			break;
		default:
			assert(0 && "unknown game event");
			break;
	}
}