Ejemplo n.º 1
0
int CanCompleteMission(struct MissionOptions *options)
{
	int i;

	// Death is the only escape from dogfights and quick play
	if (gCampaign.Entry.Mode == CAMPAIGN_MODE_DOGFIGHT)
	{
		return GetNumPlayersAlive() <= 1;
	}
	else if (gCampaign.Entry.Mode == CAMPAIGN_MODE_QUICK_PLAY)
	{
		return GetNumPlayersAlive() == 0;
	}

	// Check all objective counts are enough
	for (i = 0; i < (int)options->Objectives.size; i++)
	{
		struct Objective *o = CArrayGet(&options->Objectives, i);
		MissionObjective *mobj =
			CArrayGet(&options->missionData->Objectives, i);
		if (o->done < mobj->Required)
		{
			return 0;
		}
	}

	return 1;
}
Ejemplo n.º 2
0
void HUDNumPopupsDrawObjective(
	const HUDNumPopups *popups, const int idx, const Vec2i pos)
{
	const Objective *o = CArrayGet(&gMission.missionData->Objectives, idx);
	const HUDNumPopup *p = CArrayGet(&popups->objective, idx);
	DrawNumUpdate(p, "%d", o->done, pos, 0);
}
Ejemplo n.º 3
0
static HitType GetHitType(
	const TTileItem *ti, const TMobileObject *bullet, int *targetUID)
{
	*targetUID = -1;
	HitType ht = HIT_NONE;
	switch (ti->kind)
	{
	case KIND_CHARACTER:
		ht = HIT_FLESH;
		*targetUID = ((const TActor *)CArrayGet(&gActors, ti->id))->uid;
		break;
	case KIND_OBJECT:
		ht = HIT_OBJECT;
		*targetUID = ((const TObject *)CArrayGet(&gObjs, ti->id))->uid;
		break;
	default:
		CASSERT(false, "cannot damage target kind");
		break;
	}
	if (bullet->tileItem.SoundLock > 0 ||
		!HasHitSound(
		bullet->bulletClass->Power, bullet->flags, bullet->PlayerUID,
		ti->kind, *targetUID, bullet->bulletClass->Special, true))
	{
		ht = HIT_NONE;
	}
	return ht;
}
Ejemplo n.º 4
0
static void DrawObjectiveHighlight(
	TTileItem *ti, Tile *tile, DrawBuffer *b, Vec2i offset)
{
	color_t color;
	if (ti->flags & TILEITEM_OBJECTIVE)
	{
		// Objective
		const int objective = ObjectiveFromTileItem(ti->flags);
		const Objective *o =
			CArrayGet(&gMission.missionData->Objectives, objective);
		if (o->Flags & OBJECTIVE_HIDDEN)
		{
			return;
		}
		if (!(o->Flags & OBJECTIVE_POSKNOWN) &&
			(tile->flags & MAPTILE_OUT_OF_SIGHT))
		{
			return;
		}
		color = o->color;
	}
	else if (ti->kind == KIND_PICKUP)
	{
		// Gun pickup
		const Pickup *p = CArrayGet(&gPickups, ti->id);
		if (!PickupIsManual(p))
		{
			return;
		}
		color = colorDarker;
	}
	else
	{
		return;
	}
	
	const Vec2i pos = Vec2iNew(
		ti->x - b->xTop + offset.x, ti->y - b->yTop + offset.y);
	const int pulsePeriod = ConfigGetInt(&gConfig, "Game.FPS");
	int alphaUnscaled =
		(gMission.time % pulsePeriod) * 255 / (pulsePeriod / 2);
	if (alphaUnscaled > 255)
	{
		alphaUnscaled = 255 * 2 - alphaUnscaled;
	}
	color.a = (Uint8)alphaUnscaled;
	if (ti->getPicFunc != NULL)
	{
		Vec2i picOffset;
		const Pic *pic = ti->getPicFunc(ti->id, &picOffset);
		BlitPicHighlight(
			&gGraphicsDevice, pic, Vec2iAdd(pos, picOffset), color);
	}
	else if (ti->kind == KIND_CHARACTER)
	{
		TActor *a = CArrayGet(&gActors, ti->id);
		ActorPics pics = GetCharacterPicsFromActor(a);
		DrawActorHighlight(&pics, pos, color);
	}
}
Ejemplo n.º 5
0
static void DrawObjectiveInfo(
	const struct MissionOptions *mo, const int idx, const Vec2i pos)
{
	const MissionObjective *mobj =
		CArrayGet(&mo->missionData->Objectives, idx);
	const ObjectiveDef *o = CArrayGet(&mo->Objectives, idx);
	const CharacterStore *store = &gCampaign.Setting.characters;

	switch (mobj->Type)
	{
	case OBJECTIVE_KILL:
		{
			const Character *cd = CArrayGet(
				&store->OtherChars, CharacterStoreGetSpecialId(store, 0));
			const int i = cd->looks.face;
			TOffsetPic pic;
			pic.picIndex = cHeadPic[i][DIRECTION_DOWN][STATE_IDLE];
			pic.dx = cHeadOffset[i][DIRECTION_DOWN].dx;
			pic.dy = cHeadOffset[i][DIRECTION_DOWN].dy;
			DrawTTPic(
				pos.x + pic.dx, pos.y + pic.dy,
				PicManagerGetOldPic(&gPicManager, pic.picIndex), &cd->table);
		}
		break;
	case OBJECTIVE_RESCUE:
		{
			const Character *cd = CArrayGet(
				&store->OtherChars, CharacterStoreGetPrisonerId(store, 0));
			const int i = cd->looks.face;
			TOffsetPic pic;
			pic.picIndex = cHeadPic[i][DIRECTION_DOWN][STATE_IDLE];
			pic.dx = cHeadOffset[i][DIRECTION_DOWN].dx;
			pic.dy = cHeadOffset[i][DIRECTION_DOWN].dy;
			DrawTTPic(
				pos.x + pic.dx, pos.y + pic.dy,
				PicManagerGetOldPic(&gPicManager, pic.picIndex), &cd->table);
		}
		break;
	case OBJECTIVE_COLLECT:
		{
			const Pic *p = o->pickupClass->Pic;
			Blit(&gGraphicsDevice, p, Vec2iAdd(pos, p->offset));
		}
		break;
	case OBJECTIVE_DESTROY:
		{
			Vec2i picOffset;
			const Pic *p =
				MapObjectGetPic(IntMapObject(mobj->Index), &picOffset, false);
			Blit(&gGraphicsDevice, p, Vec2iAdd(pos, picOffset));
		}
		break;
	case OBJECTIVE_INVESTIGATE:
		// Don't draw
		return;
	default:
		CASSERT(false, "Unknown objective type");
		return;
	}
}
Ejemplo n.º 6
0
void UIObjectDraw(
	UIObject *o, GraphicsDevice *g, Vec2i pos, Vec2i mouse, CArray *drawObjs)
{
	// Draw this UIObject and its children in BFS order
	// Maintain a queue of UIObjects to draw
	if (drawObjs->elemSize == 0)
	{
		CArrayInit(drawObjs, sizeof(UIObjectDrawContext));
		UIObjectDrawContext c;
		c.obj = o;
		c.pos = pos;
		CArrayPushBack(drawObjs, &c);
		for (int i = 0; i < (int)drawObjs->size; i++)
		{
			UIObjectDrawContext *cPtr = CArrayGet(drawObjs, i);
			UIObjectDrawAndAddChildren(
				cPtr->obj, g, cPtr->pos, mouse, drawObjs);
		}
	}
	else
	{
		for (int i = 0; i < (int)drawObjs->size; i++)
		{
			UIObjectDrawContext *cPtr = CArrayGet(drawObjs, i);
			UIObjectDrawAndAddChildren(
				cPtr->obj, g, cPtr->pos, mouse, NULL);
		}
	}
}
Ejemplo n.º 7
0
TTileItem *ThingIdGetTileItem(ThingId *tid)
{
	TTileItem *ti = NULL;
	switch (tid->Kind)
	{
	case KIND_CHARACTER:
		ti = &((TActor *)CArrayGet(&gActors, tid->Id))->tileItem;
		break;
	case KIND_PARTICLE:
		ti = &((Particle *)CArrayGet(&gParticles, tid->Id))->tileItem;
		break;
	case KIND_MOBILEOBJECT:
		ti = &((TMobileObject *)CArrayGet(
			&gMobObjs, tid->Id))->tileItem;
		break;
	case KIND_OBJECT:
		ti = &((TObject *)CArrayGet(&gObjs, tid->Id))->tileItem;
		break;
	case KIND_PICKUP:
		ti = &((Pickup *)CArrayGet(&gPickups, tid->Id))->tileItem;
		break;
	default:
		CASSERT(false, "unknown tile item to get");
		break;
	}
	return ti;
}
Ejemplo n.º 8
0
static bool IsTileWalkable(Map *map, Vec2i pos)
{
    if (!IsTileWalkableOrOpenable(map, pos))
    {
        return false;
    }
    // Check if tile has a dangerous (explosive) item on it
    // For AI, we don't want to shoot it, so just walk around
    Tile *t = MapGetTile(map, pos);
    for (int i = 0; i < (int)t->things.size; i++)
    {
        ThingId *tid = CArrayGet(&t->things, i);
        // Only look for explosive objects
        if (tid->Kind != KIND_OBJECT)
        {
            continue;
        }
        TObject *o = CArrayGet(&gObjs, tid->Id);
        if (o->flags & OBJFLAG_DANGEROUS)
        {
            return false;
        }
    }
    return true;
}
Ejemplo n.º 9
0
static void SetupBadguysForMission(Mission *mission)
{
	int i;
	CharacterStore *s = &gCampaign.Setting.characters;

	CharacterStoreResetOthers(s);

	if (s->OtherChars.size == 0)
	{
		return;
	}

	for (i = 0; i < (int)mission->Objectives.size; i++)
	{
		MissionObjective *mobj = CArrayGet(&mission->Objectives, i);
		if (mobj->Type == OBJECTIVE_RESCUE)
		{
			CharacterStoreAddPrisoner(s, mobj->Index);
			break;	// TODO: multiple prisoners
		}
	}

	for (i = 0; i < (int)mission->Enemies.size; i++)
	{
		CharacterStoreAddBaddie(s, *(int *)CArrayGet(&mission->Enemies, i));
	}

	for (i = 0; i < (int)mission->SpecialChars.size; i++)
	{
		CharacterStoreAddSpecial(
			s, *(int *)CArrayGet(&mission->SpecialChars, i));
	}
}
Ejemplo n.º 10
0
bool PlayerSelection(void)
{
	PlayerSelectionData data;
	memset(&data, 0, sizeof data);
	data.IsOK = true;
	GetDataFilePath(data.prefixes, "data/prefixes.txt");
	GetDataFilePath(data.suffixes, "data/suffixes.txt");
	GetDataFilePath(data.suffixnames, "data/suffixnames.txt");
	NameGenInit(&data.g, data.prefixes, data.suffixes, data.suffixnames);

	// Create selection menus for each local player
	for (int i = 0, idx = 0; i < (int)gPlayerDatas.size; i++, idx++)
	{
		PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (!p->IsLocal)
		{
			idx--;
			continue;
		}
		PlayerSelectMenusCreate(
			&data.menus[idx], GetNumPlayers(false, false, true), idx, i,
			&gEventHandlers, &gGraphicsDevice, &data.g);
	}

	if (!gCampaign.IsClient)
	{
		NetServerOpen(&gNetServer);
	}
	GameLoopData gData = GameLoopDataNew(
		&data, PlayerSelectionUpdate,
		&data, PlayerSelectionDraw);
	GameLoop(&gData);

	if (data.IsOK)
	{
		for (int i = 0, idx = 0; i < (int)gPlayerDatas.size; i++, idx++)
		{
			PlayerData *p = CArrayGet(&gPlayerDatas, i);
			if (!p->IsLocal)
			{
				idx--;
				continue;
			}

			// For any player slots not picked, turn them into AIs
			if (p->inputDevice == INPUT_DEVICE_UNSET)
			{
				PlayerSetInputDevice(p, INPUT_DEVICE_AI, 0);
			}
		}
	}

	for (int i = 0; i < GetNumPlayers(false, false, true); i++)
	{
		MenuSystemTerminate(&data.menus[i].ms);
	}
	NameGenTerminate(&data.g);
	return data.IsOK;
}
Ejemplo n.º 11
0
static void DrawObjectiveHighlight(
	TTileItem *ti, Tile *tile, DrawBuffer *b, Vec2i offset)
{
	if (!(ti->flags & TILEITEM_OBJECTIVE))
	{
		return;
	}
	int objective = ObjectiveFromTileItem(ti->flags);
	MissionObjective *mo =
		CArrayGet(&gMission.missionData->Objectives, objective);
	if (mo->Flags & OBJECTIVE_HIDDEN)
	{
		return;
	}
	if (!(mo->Flags & OBJECTIVE_POSKNOWN) &&
		(tile->flags & MAPTILE_OUT_OF_SIGHT))
	{
		return;
	}
	Vec2i pos = Vec2iNew(
		ti->x - b->xTop + offset.x, ti->y - b->yTop + offset.y);
	struct Objective *o =
		CArrayGet(&gMission.Objectives, objective);
	color_t color = o->color;
	int pulsePeriod = FPS_FRAMELIMIT;
	int alphaUnscaled =
		(gMission.time % pulsePeriod) * 255 / (pulsePeriod / 2);
	if (alphaUnscaled > 255)
	{
		alphaUnscaled = 255 * 2 - alphaUnscaled;
	}
	color.a = (Uint8)alphaUnscaled;
	if (ti->getPicFunc != NULL)
	{
		Vec2i picOffset;
		const Pic *pic = ti->getPicFunc(ti->id, &picOffset);
		BlitPicHighlight(
			&gGraphicsDevice, pic, Vec2iAdd(pos, picOffset), color);
	}
	else if (ti->getActorPicsFunc != NULL)
	{
		ActorPics pics = ti->getActorPicsFunc(ti->id);
		// Do not highlight dead, dying or transparent characters
		if (!pics.IsDead && !pics.IsTransparent)
		{
			for (int i = 0; i < 3; i++)
			{
				if (PicIsNotNone(&pics.Pics[i]))
				{
					BlitPicHighlight(
						&gGraphicsDevice,
						&pics.Pics[i], pos, color);
				}
			}
		}
	}
}
Ejemplo n.º 12
0
static void DogfightFinalScoresDraw(void *data)
{
	UNUSED(data);

	// This will only draw once
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Work out who's the winner, or if it's a tie
	int maxScore = 0;
	int playersWithMaxScore = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (p->RoundsWon > maxScore)
		{
			maxScore = p->RoundsWon;
			playersWithMaxScore = 1;
		}
		else if (p->RoundsWon == maxScore)
		{
			playersWithMaxScore++;
		}
	}
	const bool isTie = playersWithMaxScore == (int)gPlayerDatas.size;

	// Draw players and their names spread evenly around the screen.
	// If it's a tie, display the message in the centre,
	// otherwise display the winner just below the winning player
#define DRAW_TEXT	"It's a draw!"
#define WINNER_TEXT	"Winner!"
	CASSERT(
		gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4,
		"Unimplemented number of players for dogfight");
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const Vec2i pos = Vec2iNew(
			w / 4 + (i & 1) * w / 2,
			gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2);
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		DisplayCharacterAndName(pos, &p->Char, p->name);
		ShowPlayerScore(pos, p->RoundsWon);
		if (!isTie && maxScore == p->RoundsWon)
		{
			FontStrMask(
				WINNER_TEXT,
				Vec2iNew(pos.x - FontStrW(WINNER_TEXT) / 2, pos.y + 30),
				colorGreen);
		}
	}
	if (isTie)
	{
		FontStrCenter(DRAW_TEXT);
	}
}
Ejemplo n.º 13
0
Ammo *AmmoGetById(AmmoClasses *ammo, const int id)
{
	if (id < (int)ammo->Ammo.size)
	{
		return CArrayGet(&ammo->Ammo, id);
	}
	else
	{
		return CArrayGet(&ammo->CustomAmmo, id - (int)ammo->Ammo.size);
	}
}
Ejemplo n.º 14
0
static void ActionRun(Action *a, CArray *mapTriggers)
{
	int i;
	switch (a->action)
	{
	case ACTION_NULL:
		return;

	case ACTION_SOUND:
		SoundPlayAt(&gSoundDevice, a->a.Sound, a->u.pos);
		break;

	case ACTION_SETTRIGGER:
		for (i = 0; i < (int)mapTriggers->size; i++)
		{
			Trigger *tr = *(Trigger **)CArrayGet(mapTriggers, i);
			if (tr->id == a->u.index)
			{
				tr->isActive = 1;
				break;
			}
		}
		break;

	case ACTION_CLEARTRIGGER:
		for (i = 0; i < (int)mapTriggers->size; i++)
		{
			Trigger *tr = *(Trigger **)CArrayGet(mapTriggers, i);
			if (tr->id == a->u.index)
			{
				tr->isActive = 0;
				break;
			}
		}
		break;

	case ACTION_CHANGETILE:
		{
			Tile *t= MapGetTile(&gMap, a->u.pos);
			t->flags = a->a.tileFlags;
			t->pic = a->tilePic;
			t->picAlt = a->tilePicAlt;
		}
		break;

	case ACTION_ACTIVATEWATCH:
		ActivateWatch(a->u.index);
		break;

	case ACTION_DEACTIVATEWATCH:
		DeactivateWatch(a->u.index);
		break;
	}
}
Ejemplo n.º 15
0
MapObject *IndexMapObject(const int i)
{
	CASSERT(
		i >= 0 &&
		i < (int)gMapObjects.Classes.size + (int)gMapObjects.CustomClasses.size,
		"Map object index out of bounds");
	if (i < (int)gMapObjects.Classes.size)
	{
		return CArrayGet(&gMapObjects.Classes, i);
	}
	return CArrayGet(&gMapObjects.CustomClasses, i - gMapObjects.Classes.size);
}
Ejemplo n.º 16
0
bool ScreenMissionSummary(CampaignOptions *c, struct MissionOptions *m)
{
	// Save password
	MissionSave ms;
	MissionSaveInit(&ms);
	ms.Campaign = c->Entry;
	// Don't make password for next level if there is none
	int passwordIndex = m->index + 1;
	if (passwordIndex == c->Entry.NumMissions)
	{
		passwordIndex--;
	}
	strcpy(ms.Password, MakePassword(passwordIndex, 0));
	ms.MissionsCompleted = m->index + 1;
	AutosaveAddMission(&gAutosave, &ms, ms.Campaign.BuiltinIndex);
	AutosaveSave(&gAutosave, GetConfigFilePath(AUTOSAVE_FILE));

	// Calculate bonus scores
	// Bonuses only apply if at least one player has lived
	if (AreAnySurvived())
	{
		int bonus = 0;
		// Objective bonuses
		for (int i = 0; i < (int)m->missionData->Objectives.size; i++)
		{
			const struct Objective *o = CArrayGet(&m->Objectives, i);
			const MissionObjective *mo = CArrayGet(&m->missionData->Objectives, i);
			if (o->done == mo->Count && o->done > mo->Required)
			{
				// Perfect
				bonus += PERFECT_BONUS;
			}
		}
		bonus += GetAccessBonus(m);
		bonus += GetTimeBonus(m, NULL);

		for (int i = 0; i < (int)gPlayerDatas.size; i++)
		{
			PlayerData *p = CArrayGet(&gPlayerDatas, i);
			ApplyBonuses(p, bonus);
		}
	}
	GameLoopWaitForAnyKeyOrButtonData wData;
	GameLoopData gData = GameLoopDataNew(
		&wData, GameLoopWaitForAnyKeyOrButtonFunc,
		m, MissionSummaryDraw);
	GameLoop(&gData);
	if (wData.IsOK)
	{
		SoundPlay(&gSoundDevice, StrSound("mg"));
	}
	return wData.IsOK;
}
Ejemplo n.º 17
0
static void DeathmatchFinalScoresDraw(void *data)
{
	UNUSED(data);

	// This will only draw once
	const int w = gGraphicsDevice.cachedConfig.Res.x;
	const int h = gGraphicsDevice.cachedConfig.Res.y;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Work out the highest kills
	int maxKills = 0;
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (p->kills > maxKills)
		{
			maxKills = p->kills;
		}
	}

	// Draw players and their names spread evenly around the screen.
	CASSERT(
		gPlayerDatas.size >= 2 && gPlayerDatas.size <= 4,
		"Unimplemented number of players for deathmatch");
#define LAST_MAN_TEXT	"Last man standing!"
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const Vec2i pos = Vec2iNew(
			w / 4 + (i & 1) * w / 2,
			gPlayerDatas.size == 2 ? h / 2 : h / 4 + (i / 2) * h / 2);
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		DisplayCharacterAndName(pos, &p->Char, p->name);
		
		// Kills
		char s[16];
		sprintf(s, "Kills: %d", p->kills);
		FontStrMask(
			s, Vec2iNew(pos.x - FontStrW(s) / 2, pos.y + 20),
			p->kills == maxKills ? colorGreen : colorWhite);

		// Last man standing?
		if (p->Lives > 0)
		{
			FontStrMask(
				LAST_MAN_TEXT,
				Vec2iNew(pos.x - FontStrW(LAST_MAN_TEXT) / 2, pos.y + 30),
				colorGreen);
		}
	}
}
Ejemplo n.º 18
0
GunDescription *IdGunDescription(const int i)
{
	CASSERT(
		i >= 0 &&
		i < (int)gGunDescriptions.Guns.size +
		(int)gGunDescriptions.CustomGuns.size,
		"Gun index out of bounds");
	if (i < (int)gGunDescriptions.Guns.size)
	{
		return CArrayGet(&gGunDescriptions.Guns, i);
	}
	return CArrayGet(
		&gGunDescriptions.CustomGuns, i - gGunDescriptions.Guns.size);
}
Ejemplo n.º 19
0
void PicManagerClear(CArray *pics, CArray *sprites)
{
	for (int i = 0; i < (int)pics->size; i++)
	{
		NamedPic *n = CArrayGet(pics, i);
		CFREE(n->name);
		PicFree(&n->pic);
	}
	CArrayClear(pics);
	for (int i = 0; i < (int)sprites->size; i++)
	{
		NamedSpritesFree(CArrayGet(sprites, i));
	}
	CArrayClear(sprites);
}
Ejemplo n.º 20
0
void HealthPickupsUpdate(HealthPickups *h, int ticks)
{
	// Don't spawn pickups if not allowed
	if (!AreHealthPickupsAllowed(gCampaign.Entry.Mode) ||
		!gConfig.Game.HealthPickups)
	{
		return;
	}

	double scalar = 1.0;
	// Update time until next spawn based on:
	// Damage taken (find player with lowest health)
	int minHealth = ModeMaxHealth(gCampaign.Entry.Mode);
	int maxHealth = minHealth;
	for (int i = 0; i < (int)gPlayerDatas.size; i++)
	{
		const PlayerData *p = CArrayGet(&gPlayerDatas, i);
		if (!IsPlayerAlive(p))
		{
			continue;
		}
		const TActor *player = CArrayGet(&gActors, p->Id);
		minHealth = MIN(minHealth, player->health);
	}
	// Double spawn rate if near 0 health
	scalar *= (minHealth + maxHealth) / (maxHealth * 2.0);

	// Scale down over time
	scalar *= pow(TIME_DECAY_EXPONENT, h->pickupsSpawned);

	h->timeUntilNextSpawn = (int)floor(scalar * SPAWN_TIME);

	// Update time
	h->timer += ticks;

	// Attempt to add health if time reached, and we haven't placed too many
	if (h->timer >= h->timeUntilNextSpawn &&
		h->map->NumExplorableTiles / MAX_TILES_PER_PICKUP + 1 > h->numPickups)
	{
		h->timer = 0;

		if (TryPlacePickup(h))
		{
			h->pickupsSpawned++;
			h->numPickups++;
		}
	}
}
Ejemplo n.º 21
0
static void LoadGunSpawners(CArray *classes, const CArray *guns)
{
	for (int i = 0; i < (int)guns->size; i++)
	{
		const GunDescription *g = CArrayGet(guns, i);
		if (!g->IsRealGun)
		{
			continue;
		}
		MapObject m;
		memset(&m, 0, sizeof m);
		char buf[256];
		sprintf(buf, "%s spawner", g->name);
		CSTRDUP(m.Name, buf);
		m.Normal.Pic = PicManagerGetPic(&gPicManager, "spawn_pad");
		m.Normal.Offset = Vec2iNew(
			-m.Normal.Pic->size.x / 2,
			TILE_HEIGHT / 2 - m.Normal.Pic->size.y);
		m.Size = Vec2iNew(TILE_WIDTH, TILE_HEIGHT);
		m.Health = 0;
		m.Type = MAP_OBJECT_TYPE_PICKUP_SPAWNER;
		sprintf(buf, "gun_%s", g->name);
		m.u.PickupClass = StrPickupClass(buf);
		CArrayPushBack(classes, &m);
	}
}
Ejemplo n.º 22
0
static void MissionBriefingDraw(void *data)
{
	const MissionBriefingData *mData = data;

	GraphicsBlitBkg(&gGraphicsDevice);

	// Mission title
	FontStrOpt(mData->Title, Vec2iZero(), mData->TitleOpts);
	// Display password
	FontStrOpt(mData->Password, Vec2iZero(), mData->PasswordOpts);
	// Display description with typewriter effect
	FontStr(mData->TypewriterBuf, mData->DescriptionPos);
	// Display objectives
	for (int i = 0;
		i < (int)mData->MissionOptions->missionData->Objectives.size;
		i++)
	{
		const MissionObjective *o =
			CArrayGet(&mData->MissionOptions->missionData->Objectives, i);
		// Do not brief optional objectives
		if (o->Required == 0)
		{
			continue;
		}
		const Vec2i yInc = Vec2iNew(0, i * mData->ObjectiveHeight);
		FontStr(o->Description, Vec2iAdd(mData->ObjectiveDescPos, yInc));
		DrawObjectiveInfo(
			mData->MissionOptions, i, Vec2iAdd(mData->ObjectiveInfoPos, yInc));
	}
}
Ejemplo n.º 23
0
static TActor *AIGetClosestActor(Vec2i from, int (*compFunc)(TActor *))
{
    // Search all the actors and find the closest one that
    // satisfies the condition
    TActor *closest = NULL;
    int minDistance = -1;
    for (int i = 0; i < (int)gActors.size; i++)
    {
        TActor *a = CArrayGet(&gActors, i);
        if (!a->isInUse || a->dead)
        {
            continue;
        }
        // Never target invulnerables or civilians
        if (a->flags & (FLAGS_INVULNERABLE | FLAGS_PENALTY))
        {
            continue;
        }
        if (compFunc(a))
        {
            int distance =
                CHEBYSHEV_DISTANCE(from.x, from.y, a->Pos.x, a->Pos.y);
            if (!closest || distance < minDistance)
            {
                minDistance = distance;
                closest = a;
            }
        }
    }
    return closest;
}
Ejemplo n.º 24
0
static json_t *SaveStaticTiles(Mission *m)
{
	// Create a text buffer for CSV
	// The buffer will contain n*5 chars (tiles, allow 5 chars each),
	// and n - 1 commas, so 6n total
	const int size = (int)m->u.Static.Tiles.size;
	if (size == 0)
	{
		return json_new_string("");
	}
	char *bigbuf;
	CCALLOC(bigbuf, size * 6);
	char *pBuf = bigbuf;
	CASSERT(pBuf != NULL, "memory error");
	for (int i = 0; i < size; i++)
	{
		char buf[32];
		sprintf(buf, "%d", *(unsigned short *)CArrayGet(
			&m->u.Static.Tiles, i));
		strcpy(pBuf, buf);
		pBuf += strlen(buf);
		if (i < size - 1)
		{
			*pBuf = ',';
			pBuf++;
		}
	}
	json_t *node = json_new_string(bigbuf);
	CFREE(bigbuf);
	return node;
}
Ejemplo n.º 25
0
TObject *AIGetObjectRunningInto(TActor *a, int cmd)
{
    // Check the position just in front of the character;
    // check if there's a (non-dangerous) object in front of it
    Vec2i frontPos = Vec2iFull2Real(a->Pos);
    TTileItem *item;
    if (cmd & CMD_LEFT)
    {
        frontPos.x--;
    }
    else if (cmd & CMD_RIGHT)
    {
        frontPos.x++;
    }
    if (cmd & CMD_UP)
    {
        frontPos.y--;
    }
    else if (cmd & CMD_DOWN)
    {
        frontPos.y++;
    }
    item = GetItemOnTileInCollision(
               &a->tileItem,
               frontPos,
               TILEITEM_IMPASSABLE,
               CalcCollisionTeam(1, a),
               gCampaign.Entry.Mode == CAMPAIGN_MODE_DOGFIGHT);
    if (!item || item->kind != KIND_OBJECT)
    {
        return NULL;
    }
    return CArrayGet(&gObjs, item->id);
}
Ejemplo n.º 26
0
TBadGuy ConvertTBadGuy(Character *e)
{
	TBadGuy b;
	b.armedBodyPic = BODY_ARMED;
	b.unarmedBodyPic = BODY_UNARMED;
	b.facePic = e->looks.face;
	b.speed = e->speed;
	b.probabilityToMove = e->bot->probabilityToMove;
	b.probabilityToTrack = e->bot->probabilityToTrack;
	b.probabilityToShoot = e->bot->probabilityToShoot;
	b.actionDelay = e->bot->actionDelay;
	for (int i = 0; i < (int)gGunDescriptions.size; i++)
	{
		const GunDescription *g = CArrayGet(&gGunDescriptions, i);
		if (strcmp(e->Gun->name, g->name) == 0)
		{
			b.gun = i;
			break;
		}
	}
	b.skinColor = e->looks.skin;
	b.armColor = e->looks.arm;
	b.bodyColor = e->looks.body;
	b.legColor = e->looks.leg;
	b.hairColor = e->looks.hair;
	b.health = e->maxHealth;
	b.flags = e->flags;
	return b;
}
Ejemplo n.º 27
0
void MenuDisplay(const MenuSystem *ms)
{
	const menu_t *menu = ms->current;
	if (menu->type == MENU_TYPE_CUSTOM)
	{
		menu->u.customData.displayFunc(
			menu, ms->graphics, ms->pos, ms->size, menu->u.customData.data);
	}
	else
	{
		MenuDisplayItems(ms);

		if (strlen(menu->u.normal.title) != 0)
		{
			FontOpts opts = FontOptsNew();
			opts.HAlign = ALIGN_CENTER;
			opts.Area = ms->size;
			opts.Pad = Vec2iNew(20, 20);
			FontStrOpt(menu->u.normal.title, ms->pos, opts);
		}

		MenuDisplaySubmenus(ms);
	}
	for (int i = 0; i < (int)ms->customDisplayFuncs.size; i++)
	{
		MenuCustomDisplayFunc *cdf = CArrayGet(&ms->customDisplayFuncs, i);
		cdf->Func(NULL, ms->graphics, ms->pos, ms->size, cdf->Data);
	}
	if (menu->customDisplayFunc)
	{
		menu->customDisplayFunc(
			menu, ms->graphics, ms->pos, ms->size, menu->customDisplayData);
	}
}
static char *MakeMapObjectTooltip(const MapObject *mo)
{
	// Add a descriptive tooltip for the map object
	char buf[512];
	// Construct text representing explosion guns
	char exBuf[256];
	strcpy(exBuf, "");
	if (mo->DestroyGuns.size > 0)
	{
		sprintf(exBuf, "\nExplodes: ");
		for (int i = 0; i < (int)mo->DestroyGuns.size; i++)
		{
			if (i > 0)
			{
				strcat(exBuf, ", ");
			}
			const GunDescription **g = CArrayGet(&mo->DestroyGuns, i);
			strcat(exBuf, (*g)->name);
		}
	}
	sprintf(buf, "%s\nHealth: %d%s", mo->Name, mo->Health, exBuf);
	char *tmp;
	CSTRDUP(tmp, buf);
	return tmp;
}
Ejemplo n.º 29
0
void CollideAllItems(
	const TTileItem *item, const Vec2i pos,
	const int mask, const CollisionTeam team, const bool isPVP,
	CollideItemFunc func, void *data)
{
	const Vec2i tv = Vec2iToTile(pos);
	Vec2i dv;
	// Check collisions with all other items on this tile, in all 8 directions
	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;
			}
			CArray *tileThings = &MapGetTile(&gMap, dtv)->things;
			for (int i = 0; i < (int)tileThings->size; i++)
			{
				TTileItem *ti = ThingIdGetTileItem(CArrayGet(tileThings, i));
				// Don't collide if items are on the same team
				if (!CollisionIsOnSameTeam(ti, team, isPVP))
				{
					if (item != ti &&
						(ti->flags & mask) &&
						ItemsCollide(item, ti, pos))
					{
						func(ti, data);
					}
				}
			}
		}
	}
}
Ejemplo n.º 30
0
TTileItem *GetItemOnTileInCollision(
	TTileItem *item, Vec2i pos, int mask, CollisionTeam team, int isDogfight)
{
	Vec2i tv = Vec2iToTile(pos);
	Vec2i dv;
	if (!MapIsTileIn(&gMap, tv))
	{
		return NULL;
	}

	// Check collisions with all other items on this tile, in all 8 directions
	for (dv.y = -1; dv.y <= 1; dv.y++)
	{
		for (dv.x = -1; dv.x <= 1; dv.x++)
		{
			CArray *tileThings = &MapGetTile(&gMap, Vec2iAdd(tv, dv))->things;
			for (int i = 0; i < (int)tileThings->size; i++)
			{
				TTileItem *ti = ThingIdGetTileItem(CArrayGet(tileThings, i));
				// Don't collide if items are on the same team
				if (!CollisionIsOnSameTeam(ti, team, isDogfight))
				{
					if (item != ti &&
						(ti->flags & mask) &&
						ItemsCollide(item, ti, pos))
					{
						return ti;
					}
				}
			}
		}
	}

	return NULL;
}