Add door close delay (fixes #206)

This commit is contained in:
Cong
2015-06-14 17:02:37 +10:00
parent a9b608ec55
commit ba4a7fd5e8
8 changed files with 115 additions and 105 deletions

BIN
sounds/door_close.ogg Normal file

Binary file not shown.

3
sounds/door_close.txt Normal file
View File

@@ -0,0 +1,3 @@
Derived from Slide by jberkuta14
https://www.freesound.org/people/jberkuta14/sounds/134894/
http://creativecommons.org/publicdomain/zero/1.0/

View File

@@ -194,6 +194,8 @@ static void PicLoadOffset(Pic *picAlt, const int idx)
picAlt->Data = oldPic->Data;
picAlt->offset = Vec2iNew(cGeneralPics[idx].dx, cGeneralPics[idx].dy);
}
// 1 second to close doors
#define CLOSE_DOOR_TICKS FPS_FRAMELIMIT
// Create the watch responsible for closing the door
static TWatch *CreateCloseDoorWatch(
Map *map, const Mission *m, const Vec2i v,
@@ -208,19 +210,13 @@ static TWatch *CreateCloseDoorWatch(
for (int i = 0; i < doorGroupCount; i++)
{
const Vec2i vI = Vec2iAdd(v, Vec2iScale(dv, i));
Condition *c;
c = WatchAddCondition(w);
c->condition = CONDITION_TILECLEAR;
c->pos = Vec2iNew(vI.x - dAside.x, vI.y - dAside.y);
c = WatchAddCondition(w);
c->condition = CONDITION_TILECLEAR;
c->pos = vI;
c = WatchAddCondition(w);
c->condition = CONDITION_TILECLEAR;
c->pos = Vec2iNew(vI.x + dAside.x, vI.y + dAside.y);
WatchAddCondition(
w, CONDITION_TILECLEAR, CLOSE_DOOR_TICKS, Vec2iMinus(vI, dAside));
WatchAddCondition(
w, CONDITION_TILECLEAR, CLOSE_DOOR_TICKS, vI);
WatchAddCondition(
w, CONDITION_TILECLEAR, CLOSE_DOOR_TICKS, Vec2iAdd(vI, dAside));
}
// Now the actions of the watch once it's triggered
@@ -230,12 +226,12 @@ static TWatch *CreateCloseDoorWatch(
a = WatchAddAction(w);
a->Type = ACTION_DEACTIVATEWATCH;
a->u.index = w->index;
// play sound at the center of the door group
// play close sound at the center of the door group
a = WatchAddAction(w);
a->Type = ACTION_SOUND;
a->u.pos = Vec2iCenterOfTile(
Vec2iAdd(v, Vec2iScale(dv, doorGroupCount / 2)));
a->a.Sound = StrSound("door");
a->a.Sound = StrSound("door_close");
// Close doors
for (int i = 0; i < doorGroupCount; i++)

View File

@@ -47,6 +47,7 @@ void GrafxMakeRandomBackground(
ObjsInit();
MobObjsInit();
PickupsInit();
WatchesInit();
SetupQuickPlayCampaign(&co->Setting);
co->seed = rand();
tint.h = rand() * 360.0 / RAND_MAX;
@@ -62,7 +63,7 @@ void GrafxMakeRandomBackground(
ObjsTerminate();
MobObjsTerminate();
PickupsTerminate();
RemoveAllWatches();
WatchesTerminate();
MissionOptionsTerminate(mo);
CampaignSettingTerminate(&co->Setting);
co->seed = ConfigGetInt(&gConfig, "Game.RandomSeed");

View File

@@ -470,15 +470,10 @@ void SetupMission(
MobObjsInit();
PickupsInit();
ParticlesInit(&gParticles);
WatchesInit();
SetupObjectives(mo, m);
SetupBadguysForMission(m);
SetupWeapons(&mo->Weapons, &m->Weapons);
// TODO: store colours instead and request during map load
/*RecolourPics(
abs(m->WallColor) % COLORRANGE_COUNT,
abs(m->FloorColor) % COLORRANGE_COUNT,
abs(m->RoomColor) % COLORRANGE_COUNT,
abs(m->AltColor) % COLORRANGE_COUNT);*/
if (buildTables)
{
BuildTranslationTables(gPicManager.palette);
@@ -492,7 +487,7 @@ void MissionEnd(void)
MobObjsTerminate();
PickupsTerminate();
ParticlesTerminate(&gParticles);
RemoveAllWatches();
WatchesTerminate();
for (int i = 0; i < (int)gPlayerDatas.size; i++)
{
PlayerData *p = CArrayGet(&gPlayerDatas, i);

View File

@@ -55,8 +55,7 @@
#include "sounds.h"
#include "utils.h"
static TWatch *activeWatches = NULL;
static TWatch *inactiveWatches = NULL;
CArray gWatches; // of TWatch
static int watchIndex = 1;
@@ -83,19 +82,24 @@ Action *TriggerAddAction(Trigger *t)
TWatch *WatchNew(void)
{
TWatch *t;
CCALLOC(t, sizeof(TWatch));
t->index = watchIndex++;
t->next = inactiveWatches;
inactiveWatches = t;
CArrayInit(&t->actions, sizeof(Action));
CArrayInit(&t->conditions, sizeof(Condition));
return t;
TWatch t;
memset(&t, 0, sizeof(TWatch));
t.index = watchIndex++;
CArrayInit(&t.actions, sizeof(Action));
CArrayInit(&t.conditions, sizeof(Condition));
t.active = false;
CArrayPushBack(&gWatches, &t);
return CArrayGet(&gWatches, gWatches.size - 1);
}
Condition *WatchAddCondition(TWatch *w)
Condition *WatchAddCondition(
TWatch *w, const ConditionType type, const int counterMax,
const Vec2i pos)
{
Condition c;
memset(&c, 0, sizeof c);
c.Type = type;
c.CounterMax = counterMax;
c.Pos = pos;
CArrayPushBack(&w->conditions, &c);
return CArrayGet(&w->conditions, w->conditions.size - 1);
}
@@ -109,58 +113,52 @@ Action *WatchAddAction(TWatch *w)
static void ActivateWatch(int idx)
{
TWatch **h = &inactiveWatches;
TWatch *t;
for (int i = 0; i < (int)gWatches.size; i++)
{
TWatch *w = CArrayGet(&gWatches, i);
if (w->index == idx)
{
w->active = true;
while (*h && (*h)->index != idx)
{
h = &((*h)->next);
}
if (*h)
{
t = *h;
*h = t->next;
t->next = activeWatches;
activeWatches = t;
// Reset all conditions related to watch
for (int j = 0; j < (int)w->conditions.size; j++)
{
Condition *c = CArrayGet(&w->conditions, j);
c->Counter = 0;
}
break;
}
}
CASSERT(false, "Cannot find watch");
}
static void DeactivateWatch(int idx)
{
TWatch **h = &activeWatches;
TWatch *t;
while (*h && (*h)->index != idx)
for (int i = 0; i < (int)gWatches.size; i++)
{
h = &((*h)->next);
}
if (*h)
{
t = *h;
*h = t->next;
t->next = inactiveWatches;
inactiveWatches = t;
TWatch *w = CArrayGet(&gWatches, i);
if (w->index == idx)
{
w->active = false;
break;
}
}
CASSERT(false, "Cannot find watch");
}
void RemoveAllWatches(void)
void WatchesInit(void)
{
TWatch *t;
while (activeWatches) {
t = activeWatches;
activeWatches = t->next;
CArrayTerminate(&t->conditions);
CArrayTerminate(&t->actions);
CFREE(t);
}
while (inactiveWatches) {
t = inactiveWatches;
inactiveWatches = t->next;
CArrayTerminate(&t->conditions);
CArrayTerminate(&t->actions);
CFREE(t);
CArrayInit(&gWatches, sizeof(TWatch));
}
void WatchesTerminate(void)
{
for (int i = 0; i < (int)gWatches.size; i++)
{
TWatch *w = CArrayGet(&gWatches, i);
CArrayTerminate(&w->conditions);
CArrayTerminate(&w->actions);
}
CArrayTerminate(&gWatches);
}
static void ActionRun(Action *a, CArray *mapTriggers)
@@ -217,23 +215,32 @@ static void ActionRun(Action *a, CArray *mapTriggers)
}
}
static int ConditionsMet(CArray *conditions)
static bool ConditionsMet(CArray *conditions, const int ticks)
{
int i;
for (i = 0; i < (int)conditions->size; i++)
bool allConditionsMet = true;
for (int i = 0; i < (int)conditions->size; i++)
{
Condition *c = CArrayGet(conditions, i);
switch (c->condition)
bool conditionMet = false;
switch (c->Type)
{
case CONDITION_TILECLEAR:
if (!TileIsClear(MapGetTile(&gMap, c->pos)))
{
return 0;
}
conditionMet = TileIsClear(MapGetTile(&gMap, c->Pos));
break;
}
if (conditionMet)
{
c->Counter += ticks;
allConditionsMet =
allConditionsMet && c->Counter >= c->CounterMax;
}
else
{
c->Counter = 0;
allConditionsMet = false;
}
}
return 1;
return allConditionsMet;
}
bool TriggerCanActivate(const Trigger *t, const int flags)
@@ -249,20 +256,17 @@ void TriggerActivate(Trigger *t, CArray *mapTriggers)
}
}
void UpdateWatches(CArray *mapTriggers)
void UpdateWatches(CArray *mapTriggers, const int ticks)
{
TWatch *a = activeWatches;
TWatch *current;
while (a) {
current = a;
a = a->next;
if (ConditionsMet(&current->conditions))
for (int i = 0; i < (int)gWatches.size; i++)
{
TWatch *w = CArrayGet(&gWatches, i);
if (!w->active) continue;
if (ConditionsMet(&w->conditions, ticks))
{
int i;
for (i = 0; i < (int)current->actions.size; i++)
for (int j = 0; j < (int)w->actions.size; j++)
{
ActionRun(CArrayGet(&current->actions, i), mapTriggers);
ActionRun(CArrayGet(&w->actions, j), mapTriggers);
}
}
}

View File

@@ -64,8 +64,6 @@ typedef enum
ACTION_SOUND
} ActionType;
#define CONDITION_TILECLEAR 1
typedef struct
{
@@ -97,29 +95,42 @@ typedef struct
} Trigger;
typedef enum
{
CONDITION_TILECLEAR = 1
} ConditionType;
typedef struct
{
int condition;
Vec2i pos;
ConditionType Type;
// How many ticks has this condition been fulfilled
// Reset to 0 when condition failed
int Counter;
int CounterMax;
Vec2i Pos;
} Condition;
struct Watch {
typedef struct
{
int index;
CArray conditions; // of Condition
CArray actions; // of Action
struct Watch *next;
};
typedef struct Watch TWatch;
bool active;
} TWatch;
bool TriggerCanActivate(const Trigger *t, const int flags);
void TriggerActivate(Trigger *t, CArray *mapTriggers);
void UpdateWatches(CArray *mapTriggers);
void UpdateWatches(CArray *mapTriggers, const int ticks);
Trigger *TriggerNew(void);
void TriggerTerminate(Trigger *t);
Action *TriggerAddAction(Trigger *t);
void WatchesInit(void);
void WatchesTerminate(void);
TWatch *WatchNew(void);
Condition *WatchAddCondition(TWatch *w);
Condition *WatchAddCondition(
TWatch *w, const ConditionType type, const int counterMax,
const Vec2i pos);
Action *WatchAddAction(TWatch *w);
void RemoveAllWatches(void);

View File

@@ -610,7 +610,7 @@ static GameLoopResult RunGameUpdate(void *data)
UpdateMobileObjects(ticksPerFrame);
ParticlesUpdate(&gParticles, ticksPerFrame);
UpdateWatches(&rData->map->triggers);
UpdateWatches(&rData->map->triggers, ticksPerFrame);
PowerupSpawnerUpdate(&rData->healthSpawner, ticksPerFrame);
for (int i = 0; i < (int)rData->ammoSpawners.size; i++)