Skip to content

Commit 49a2e6c

Browse files
committed
new invasion changes
1 parent 5f98a26 commit 49a2e6c

File tree

6 files changed

+125
-96
lines changed

6 files changed

+125
-96
lines changed

src/characters/io/v_mysql_gds.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,12 @@ void *gds_process_queue(void *unused)
579579
// MYSQL functions
580580
// *********************************
581581

582-
#define QUERY(a, ...) { char* format = strdup(myva(a, __VA_ARGS__));\
582+
#define QUERY(a, ...) { char* format = strdup(myva(a, __VA_ARGS__ ));\
583583
if (mysql_query(db, format)) { gi.dprintf("DB: %s", mysql_error(db)); };\
584584
free (format); }
585585

586+
#define QUERY2(a) { if (mysql_query(db, a)) { gi.dprintf("DB: %s", mysql_error(db)); }; }
587+
586588
#define GET_RESULT result = mysql_store_result(db);\
587589
row = mysql_fetch_row(result);
588590

@@ -1202,7 +1204,7 @@ int gds_op_save(gds_queue_t *current, MYSQL* db)
12021204

12031205
QUERY ("CALL CharacterExists(\"%s\", @exists);", esc_pname)
12041206

1205-
QUERY ("SELECT @exists;")
1207+
QUERY2 ("SELECT @exists;")
12061208

12071209
GET_RESULT
12081210

src/combat/common/v_misc.c

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "g_local.h"
2-
2+
#include <gamemodes/invasion.h>
33

44
int vrx_get_joined_players() {
55
edict_t *player;
@@ -185,7 +185,7 @@ int PVM_TotalMonstersValue(edict_t* monster_owner)
185185
return (int)temp;
186186
}
187187

188-
int PVM_TotalMonsters(edict_t *monster_owner, qboolean update) {
188+
int vrx_pvm_update_total_owned_monsters(edict_t *monster_owner, qboolean update) {
189189
int i = 0;
190190
edict_t *e = NULL;
191191

@@ -205,7 +205,7 @@ int PVM_TotalMonsters(edict_t *monster_owner, qboolean update) {
205205
return monster_owner->num_monsters_real; // will this work?
206206
}
207207

208-
int PVM_RemoveAllMonsters(edict_t *monster_owner) {
208+
int vrx_remove_all_monsters(edict_t *monster_owner) {
209209
int i = 0;
210210
edict_t *e = NULL;
211211

@@ -228,7 +228,7 @@ void FindMonsterSpot(edict_t *self) {
228228
int players = vrx_get_joined_players();
229229
int total_monsters, max_monsters = 0;
230230
int mtype = 0, num = 0, i = 0;
231-
total_monsters = PVM_TotalMonsters(self, false);
231+
total_monsters = vrx_pvm_update_total_owned_monsters(self, false);
232232

233233
max_monsters = level.r_monsters;
234234

@@ -237,7 +237,7 @@ void FindMonsterSpot(edict_t *self) {
237237
max_monsters = dm_monsters->value;
238238

239239
if (level.time > self->delay) {
240-
total_monsters = PVM_TotalMonsters(self, true);
240+
total_monsters = vrx_pvm_update_total_owned_monsters(self, true);
241241
// adjust spawning delay based on efficiency of player monster kills
242242
if (total_monsters < max_monsters) {
243243
if (total_monsters < 0.5 * max_monsters) {
@@ -310,8 +310,6 @@ void SpawnRandomBoss(edict_t *self) {
310310
self->nextthink = level.time + 60.0;// try again in 1 minute
311311
}
312312

313-
void INV_SpawnMonsters(edict_t *self);
314-
315313
edict_t *InitMonsterEntity(qboolean manual_spawn) {
316314
edict_t *monster;
317315

@@ -335,9 +333,10 @@ edict_t *InitMonsterEntity(qboolean manual_spawn) {
335333
monster->think = SpawnRandomBoss;//4.4
336334
else */
337335
// most of the time people don't like having their pvp interrupted by a boss
338-
if (INVASION_OTHERSPAWNS_REMOVED)
336+
if (INVASION_OTHERSPAWNS_REMOVED) {
339337
monster->think = INV_SpawnMonsters;
340-
else
338+
monster->notify_drone_death = INV_NotifyMonsterDeath;
339+
} else
341340
monster->think = FindMonsterSpot;
342341

343342
monster->nextthink = pregame_time->value + FRAMETIME;

src/entities/drone/drone_misc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ void DroneList_Remove(edict_t *ent)
103103
DroneList[DroneCount] = NULL; // we moved the monster at the end of the list, so now the end of the list is NULL
104104

105105
ent->monsterinfo.dronelist_index = -1; // this monster has been removed from the drone list
106+
if (ent->activator && ent->activator->notify_drone_death) {
107+
ent->activator->notify_drone_death(ent);
108+
}
106109
}
107110
#ifdef _DEBUG
108111
else {

src/g_local.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,7 @@ struct edict_s
18081808
void (*pain)(edict_t *self, edict_t *other, float kick, int damage);
18091809
void (*pain_inner)(edict_t* self, edict_t* other, float kick, int damage); // az: for monsters that use drone_pain
18101810
void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
1811+
void (*notify_drone_death)(edict_t *self);
18111812

18121813
float touch_debounce_time; // are all these legit? do we need more/less of them?
18131814
float pain_debounce_time;

src/gamemodes/invasion.c

Lines changed: 106 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#include "g_local.h"
22
#include "invasion.h"
33

4+
#define MAX_ACTIVE_MONSTERS 20
5+
// 70% of the wave needs to be cleared to advance
6+
#define WAVE_CLEAR_THRESHOLD 0.7
7+
48
//FIXME: need queue that holds all players that are waiting to respawn but all spawns are busy
59
edict_t *INV_SpawnQue[MAX_CLIENTS];
610
int invasion_max_playerspawns;
@@ -56,6 +60,7 @@ void INV_Init(void)
5660
if (!pvm->value || !invasion->value)
5761
return;
5862

63+
memset(&invasion_data, 0, sizeof (struct invdata_s));
5964
INV_InitSpawnQue();
6065
INVASION_OTHERSPAWNS_REMOVED = false;
6166
invasion_difficulty_level = 1;
@@ -490,8 +495,8 @@ edict_t* INV_SpawnDrone(edict_t* self, edict_t *spawn_point, int index)
490495
}
491496
else if (invasion->value == 2) // hard mode
492497
{
493-
float plog = log2(vrx_get_joined_players() + 1) / log2(4);
494-
mhealth = 1 + 0.1 * invasion_difficulty_level * max(plog, 0);
498+
float plog = log2(vrx_get_joined_players() + 1) / log2(8);
499+
mhealth = 1 + 0.2 * sqrt(invasion_difficulty_level) * max(plog, 0);
495500
}
496501

497502
monster->max_health = monster->health = monster->max_health*mhealth;
@@ -632,10 +637,12 @@ void INV_OnTimeout(edict_t *self) {
632637
}
633638
// remove monsters from the current wave before spawning the next
634639
if (self->num_monsters_real)
635-
PVM_RemoveAllMonsters(self);
636-
// restart the last wave
637-
if (!was_boss)
640+
vrx_remove_all_monsters(self);
641+
642+
// restart the last wave if we were done spawning
643+
if (!was_boss && self->count == MONSTERSPAWN_STATUS_IDLE) {
638644
invasion_difficulty_level -= 1;
645+
}
639646

640647
// increase the difficulty level for the next wave
641648
//if (invasion->value == 1)
@@ -699,6 +706,9 @@ void INV_ShowLastWaveSummary() {
699706
}
700707

701708
void INV_OnBeginWave(edict_t *self, int max_monsters) {
709+
invasion_data.limitframe = level.time + TimeFormula();
710+
invasion_data.printedmessage = true;
711+
702712
if (invasion_difficulty_level == 1)
703713
{
704714
if (invasion->value == 1)
@@ -716,6 +726,7 @@ void INV_OnBeginWave(edict_t *self, int max_monsters) {
716726
G_PrintGreenText(va("Timelimit: %dm %ds.\n", (int)TimeFormula() / 60, (int)TimeFormula() % 60));
717727

718728
gi.sound(&g_edicts[0], CHAN_VOICE, gi.soundindex("misc/talk1.wav"), 1, ATTN_NONE, 0);
729+
invasion_data.remaining_monsters = max_monsters * WAVE_CLEAR_THRESHOLD;
719730

720731
// check for a boss spawn
721732
INV_BossCheck(self);
@@ -800,21 +811,93 @@ void INV_SelectMonsterSet(const edict_t* self, int const * * monster_set, int* m
800811
}
801812
}
802813

814+
void INV_Spawnstate_Idle(edict_t *self, const int players) {
815+
// if there's nobody playing, remove all monsters
816+
817+
if (players < 1)
818+
{
819+
// az: reset the current wave to avoid people skipping waves
820+
if (self->num_monsters_real) {
821+
invasion_difficulty_level -= 1;
822+
invasion_data.printedmessage = false;
823+
vrx_remove_all_monsters(self);
824+
}
825+
}
826+
}
827+
828+
qboolean INV_Spawnstate_Working(edict_t *self, const int players, int max_monsters, edict_t *e) {
829+
int SpawnTries = 0, MaxTriesThisFrame = 32;
830+
831+
if (players < 1)
832+
{
833+
return true;
834+
}
835+
836+
// print the message and set the timer the first frame we start working
837+
if (!invasion_data.printedmessage) {
838+
INV_OnBeginWave(self, max_monsters);
839+
INV_SelectMonsterSet(NULL, &invasion_data.monster_set, &invasion_data.monster_set_count);
840+
}
841+
842+
while ((e = INV_GetMonsterSpawn(e))
843+
&& invasion_data.mspawned < max_monsters
844+
&& self->num_monsters_real < MAX_ACTIVE_MONSTERS
845+
&& SpawnTries < MaxTriesThisFrame)
846+
{
847+
//const int* monster_set;
848+
//int monster_set_count;
849+
int pick;
850+
int monster ;
851+
852+
INV_SelectMonsterSet(e, &invasion_data.monster_set, &invasion_data.monster_set_count);
853+
pick = GetRandom(1, invasion_data.monster_set_count) - 1;
854+
monster = invasion_data.monster_set[pick];
855+
856+
SpawnTries++;
857+
if (INV_SpawnDrone(self, e, monster)) // Wait for now
858+
invasion_data.mspawned++;
859+
}
860+
861+
if (invasion_data.mspawned >= max_monsters)
862+
{
863+
// increase the difficulty level for the next wave
864+
invasion_difficulty_level += 1;
865+
invasion_data.printedmessage = 0;
866+
invasion_data.mspawned = 0;
867+
self->count = MONSTERSPAWN_STATUS_IDLE;
868+
//gi.dprintf("invasion level now: %d\n", invasion_difficulty_level);
869+
}
870+
return false;
871+
}
872+
873+
void INV_NotifyMonsterDeath(edict_t * edict) {
874+
invasion_data.remaining_monsters--;
875+
}
876+
803877
void INV_SpawnMonsters(edict_t *self)
804878
{
805879
const int players = vrx_get_joined_players();
806880

807881
// How many monsters should we spawn?
808882
// 10 at lv 1, 30 by level 20. 41 by level 100
809-
int max_monsters = (int)round(10 + 4.6276 * log2f((float)invasion_difficulty_level));
883+
int max_monsters = (int)round(10 + 4.6276 * (float)(invasion_difficulty_level - 1));
810884

811885
edict_t *e = NULL;
812-
int SpawnTries = 0, MaxTriesThisFrame = 32;
886+
887+
self->nextthink = level.time + FRAMETIME;
888+
889+
// the level ended, remove monsters
890+
if (level.intermissiontime)
891+
{
892+
if (self->num_monsters_real)
893+
vrx_remove_all_monsters(self);
894+
return;
895+
}
813896

814897
// get the value of all of our monsters (BF flag mult * level * control_cost)
815898
// max_monsters_value = PVM_TotalMonstersValue(self);
816899
// update our drone count
817-
PVM_TotalMonsters(self, true);
900+
vrx_pvm_update_total_owned_monsters(self, true);
818901

819902
//max_monsters = 1;//GHz DEBUG - REMOVE ME!
820903
//self->nextthink = level.time + FRAMETIME;//GHz DEBUG - REMOVE ME!
@@ -828,99 +911,37 @@ void INV_SpawnMonsters(edict_t *self)
828911
max_monsters = 6 * (vrx_get_joined_players() - 1);
829912
}
830913

831-
// Idle State
832-
// we're done spawning
833-
if (self->count == MONSTERSPAWN_STATUS_IDLE)
834-
{
835-
// if there's nobody playing, remove all monsters
836-
if (players < 1)
837-
{
838-
// az: reset the current wave to avoid people skipping waves
839-
if (self->num_monsters_real) {
840-
invasion_difficulty_level -= 1;
841-
invasion_data.printedmessage = false;
842-
PVM_RemoveAllMonsters(self);
843-
}
844-
}
845-
846-
// the level ended, remove monsters
847-
if (level.intermissiontime)
848-
{
849-
if (self->num_monsters_real)
850-
PVM_RemoveAllMonsters(self);
851-
return;
852-
}
853-
854-
// were all monsters eliminated?
855-
if (self->num_monsters_real == 0) {
856-
// start spawning
857-
self->nextthink = level.time + FRAMETIME;
858-
self->count = MONSTERSPAWN_STATUS_WORKING;
859-
return;
860-
}
861-
914+
// were enough monsters eliminated?
915+
if (invasion_data.remaining_monsters <= 0 && !invasion_data.boss) {
916+
// start spawning
917+
self->count = MONSTERSPAWN_STATUS_WORKING;
918+
}
862919

863-
// Check for timeout
920+
// Check for timeout if there are players
921+
if (players >= 1 && invasion_difficulty_level > 1) {
864922
if (invasion_data.limitframe > level.time) // we still got time?
865923
{
866924
self->nextthink = level.time + FRAMETIME;
867-
return;
868925
}
869926
else
870927
{
871928
// Timeout. We go straight to the working state.
872929
INV_OnTimeout(self);
873-
//self->count = MONSTERSPAWN_STATUS_WORKING;
874-
return;
875930
}
876931
}
877932

878-
// Working State
879-
//gi.dprintf("%d: level: %d max_monsters: %d\n", (int)(level.framenum), invasion_difficulty_level, max_monsters);
880-
// if there's nobody playing, then wait until some join
881-
if (players < 1)
933+
// Idle State
934+
// we're done spawning
935+
if (self->count == MONSTERSPAWN_STATUS_IDLE)
882936
{
883-
self->nextthink = level.time + FRAMETIME;
937+
INV_Spawnstate_Idle(self, players);
884938
return;
885939
}
886940

887-
// print the message and set the timer the first frame we start working
888-
if (!invasion_data.printedmessage) {
889-
invasion_data.limitframe = level.time + TimeFormula();
890-
INV_OnBeginWave(self, max_monsters);
891-
invasion_data.printedmessage = true;
892-
INV_SelectMonsterSet(NULL, &invasion_data.monster_set, &invasion_data.monster_set_count);
893-
}
894-
895-
self->nextthink = level.time + FRAMETIME;
896-
897-
while ((e = INV_GetMonsterSpawn(e))
898-
&& invasion_data.mspawned < max_monsters
899-
&& SpawnTries < MaxTriesThisFrame)
900-
{
901-
//const int* monster_set;
902-
//int monster_set_count;
903-
int pick;
904-
int monster ;
905-
906-
INV_SelectMonsterSet(e, &invasion_data.monster_set, &invasion_data.monster_set_count);
907-
pick = GetRandom(1, invasion_data.monster_set_count) - 1;
908-
monster = invasion_data.monster_set[pick];
909-
910-
SpawnTries++;
911-
if (INV_SpawnDrone(self, e, monster)) // Wait for now
912-
invasion_data.mspawned++;
913-
}
914-
915-
if (invasion_data.mspawned >= max_monsters)
916-
{
917-
// increase the difficulty level for the next wave
918-
invasion_difficulty_level += 1;
919-
invasion_data.printedmessage = 0;
920-
invasion_data.mspawned = 0;
921-
self->count = MONSTERSPAWN_STATUS_IDLE;
922-
//gi.dprintf("invasion level now: %d\n", invasion_difficulty_level);
923-
}
941+
// Working State
942+
//gi.dprintf("%d: level: %d max_monsters: %d\n", (int)(level.framenum), invasion_difficulty_level, max_monsters);
943+
// if there's nobody playing, then wait until some join
944+
INV_Spawnstate_Working(self, players, max_monsters, e);
924945
}
925946

926947
void INV_SpawnPlayers(void)

src/gamemodes/invasion.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct invdata_s
88
// working monster set
99
const int* monster_set;
1010
int monster_set_count;
11+
int remaining_monsters;
1112
// default monster set - may be overridden by spawn
1213
const int* default_monster_set;
1314
int default_set_count;
@@ -18,3 +19,5 @@ struct invdata_s
1819
extern struct invdata_s invasion_data;
1920

2021
int G_GetEntityIndex(edict_t *ent);
22+
void INV_SpawnMonsters(edict_t *self);
23+
void INV_NotifyMonsterDeath(edict_t * edict);

0 commit comments

Comments
 (0)