marrub
/
Lithia
Archived
1
0
Fork 0
This repository has been archived on 2023-06-17. You can view files and clone it, but cannot push or open issues/pull-requests.
Lithia/source/Main/w_boss.c

261 lines
5.7 KiB
C

// Copyright © 2016-2017 Graham Sanderson, all rights reserved.
// vim: columns=100
#include "lith_common.h"
#include "lith_player.h"
#include "lith_world.h"
// Types ---------------------------------------------------------------------|
struct boss
{
__str const name;
int const phasenum;
int phase;
bool dead;
list_t link;
};
enum
{
diff_easy,
diff_medi,
diff_hard,
diff_any,
diff_max
};
// Static Objects ------------------------------------------------------------|
static struct boss bosses_easy[] = {
{"James", 2},
};
static struct boss bosses_medi[] = {
{"Makarov", 3},
};
static struct boss bosses_hard[] = {
{"Isaac", 3},
};
static struct boss *lmvar boss;
static int lmvar bosstid;
static bool alldead[diff_max];
static int rewardnum;
static int difficulty;
static struct boss *lastboss;
static i96 scorethreshold = 1000000;
// Static Functions ----------------------------------------------------------|
//
// Lith_SpawnBossReward
//
static void Lith_SpawnBossReward(void)
{
int x = ACS_GetActorX(0);
int y = ACS_GetActorY(0);
int z = ACS_GetActorZ(0);
switch(rewardnum++)
{
case 0: ACS_SpawnForced("Lith_BossReward1", x, y, z); break;
case 1: ACS_SpawnForced("Lith_BossReward2", x, y, z); break;
case 2: ACS_SpawnForced("Lith_BossReward3", x, y, z); break;
case 3: ACS_SpawnForced("Lith_BossReward4", x, y, z); break;
case 4: ACS_SpawnForced("Lith_BossReward5", x, y, z); break;
case 7: ACS_SpawnForced("Lith_BossReward6", x, y, z); break;
}
}
//
// Lith_TriggerBoss
//
static void Lith_TriggerBoss(void)
{
static bool firstboss = true;
if(!boss) return;
if(boss->dead) {
Log("Lith_TriggerBoss: %S is dead, invalid num", boss->name);
boss = null;
return;
}
if(boss->phase > boss->phasenum) {
Log("Lith_TriggerBoss: invalid boss phase");
boss = null;
return;
}
if(!boss->phase)
boss->phase = 1;
LogDebug(log_boss, "Lith_TriggerBoss: Spawning boss %S phase %i", boss->name, boss->phase);
//TODO HERMES("TriggerBoss");
if(firstboss) {
firstboss = false;
Lith_ForPlayer()
p->deliverMail("Phantom");
}
}
//
// CheckDead
//
static bool CheckDead(struct boss *b, int num)
{
for(int i = 0; i < num; i++)
if(!b[i].dead) return false;
return true;
}
// Extern Functions ----------------------------------------------------------|
//
// Lith_PhantomSound
//
script acs void Lith_PhantomSound(void)
{
ACS_AmbientSound("enemies/phantom/spawned", 127);
}
//
// Lith_PhantomTeleport
//
script acs void Lith_PhantomTeleport(void)
{
fixed ang = ACS_GetActorAngle(0);
ACS_ThrustThing(ang * 256, 64, true, 0);
for(int i = 0; i < 15; i++) {
InvGive("Lith_PhantomTeleport", 1);
ACS_Delay(1);
}
}
//
// Lith_PhantomDeath
//
script acs void Lith_PhantomDeath(void)
{
ACS_StopSound(0, 7);
if(boss->phase == boss->phasenum)
{
// Death
ACS_AmbientSound("player/death1", 127);
ACS_Delay(35);
InvGive("Lith_PlayerDeath", 1);
ACS_Delay(25);
InvGive("Lith_PlayerDeathNuke", 1);
ACS_Delay(25);
Lith_ForPlayer() p->deliverMail(StrParam("%SDefeated", boss->name));
boss->dead = true;
if(difficulty != diff_any) difficulty++;
}
else
{
// Escape
ACS_AmbientSound("enemies/phantom/escape", 127);
ACS_SetActorState(0, "GetOutOfDodge");
ACS_Delay(5);
InvGive("Lith_PhantomOut", 1);
ACS_Delay(2);
}
LogDebug(log_boss, "Lith_PhantomDeath: %S phase %i defeated", boss->name, boss->phase);
Lith_SpawnBossReward();
scorethreshold = scorethreshold * 17 / 10;
DebugNote("score threshold raised to %lli", scorethreshold);
boss->phase++;
boss = null;
world.bossspawned = false;
}
//
// Lith_SpawnBoss
//
script acs void Lith_SpawnBoss(void)
{
if(!boss) return;
bosstid = ACS_ActivatorTID();
bosstid = bosstid ? bosstid : ACS_UniqueTID();
//TODO HERMES("SpawnBoss", StrParam("Lith_Boss_%S", boss->name), boss->phase);
LogDebug(log_boss, "Lith_SpawnBoss: Boss %s phase %i spawned", boss->name, boss->phase);
DebugNote("boss: %S phase %i spawned\n", boss->name, boss->phase);
world.bossspawned = true;
}
//
// Lith_TriggerBoss_Script
//
script acs address("Lith_TriggerBoss") optargs(1) void Lith_TriggerBoss_Script(int diff, int num, int phase)
{
switch(diff)
{
case diff_easy: boss = &bosses_easy[num]; break;
case diff_medi: boss = &bosses_medi[num]; break;
case diff_hard: boss = &bosses_hard[num]; break;
}
if(phase)
{boss->dead = false; boss->phase = phase;}
Lith_TriggerBoss();
}
//
// Lith_SpawnBosses
//
script acs void Lith_SpawnBosses(i96 sum, bool force)
{
if(!force && sum < scorethreshold) return;
alldead[diff_easy] = CheckDead(bosses_easy, countof(bosses_easy));
alldead[diff_medi] = CheckDead(bosses_medi, countof(bosses_medi));
alldead[diff_hard] = CheckDead(bosses_hard, countof(bosses_hard));
int diff =
difficulty == diff_any ? ACS_Random(diff_easy, diff_hard) : difficulty;
if(alldead[diff])
{
LogDebug(log_boss, "Lith_SpawnBosses: All dead, returning");
return;
}
LogDebug(log_boss, "Lith_SpawnBosses: Spawning boss, difficulty %i", diff);
if(!lastboss || lastboss->dead) switch(diff)
{
case diff_easy: do boss = &bosses_easy[ACS_Random(1, countof(bosses_easy)) - 1]; while(boss->dead); break;
case diff_medi: do boss = &bosses_medi[ACS_Random(1, countof(bosses_medi)) - 1]; while(boss->dead); break;
case diff_hard: do boss = &bosses_hard[ACS_Random(1, countof(bosses_hard)) - 1]; while(boss->dead); break;
}
else
boss = lastboss;
Lith_TriggerBoss();
}
// EOF