Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/VortexQuake2/Vortex
Browse files Browse the repository at this point in the history
  • Loading branch information
Vortex-Quake2 committed Sep 5, 2024
2 parents 1e72fa0 + 49a2e6c commit 2d6ce0c
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 96 deletions.
6 changes: 4 additions & 2 deletions src/characters/io/v_mysql_gds.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,10 +579,12 @@ void *gds_process_queue(void *unused)
// MYSQL functions
// *********************************

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

#define QUERY2(a) { if (mysql_query(db, a)) { gi.dprintf("DB: %s", mysql_error(db)); }; }

#define GET_RESULT result = mysql_store_result(db);\
row = mysql_fetch_row(result);

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

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

QUERY ("SELECT @exists;")
QUERY2 ("SELECT @exists;")

GET_RESULT

Expand Down
17 changes: 8 additions & 9 deletions src/combat/common/v_misc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "g_local.h"

#include <gamemodes/invasion.h>

int vrx_get_joined_players() {
edict_t *player;
Expand Down Expand Up @@ -185,7 +185,7 @@ int PVM_TotalMonstersValue(edict_t* monster_owner)
return (int)temp;
}

int PVM_TotalMonsters(edict_t *monster_owner, qboolean update) {
int vrx_pvm_update_total_owned_monsters(edict_t *monster_owner, qboolean update) {
int i = 0;
edict_t *e = NULL;

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

int PVM_RemoveAllMonsters(edict_t *monster_owner) {
int vrx_remove_all_monsters(edict_t *monster_owner) {
int i = 0;
edict_t *e = NULL;

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

max_monsters = level.r_monsters;

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

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

void INV_SpawnMonsters(edict_t *self);

edict_t *InitMonsterEntity(qboolean manual_spawn) {
edict_t *monster;

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

monster->nextthink = pregame_time->value + FRAMETIME;
Expand Down
3 changes: 3 additions & 0 deletions src/entities/drone/drone_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ void DroneList_Remove(edict_t *ent)
DroneList[DroneCount] = NULL; // we moved the monster at the end of the list, so now the end of the list is NULL

ent->monsterinfo.dronelist_index = -1; // this monster has been removed from the drone list
if (ent->activator && ent->activator->notify_drone_death) {
ent->activator->notify_drone_death(ent);
}
}
#ifdef _DEBUG
else {
Expand Down
1 change: 1 addition & 0 deletions src/g_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -1808,6 +1808,7 @@ struct edict_s
void (*pain)(edict_t *self, edict_t *other, float kick, int damage);
void (*pain_inner)(edict_t* self, edict_t* other, float kick, int damage); // az: for monsters that use drone_pain
void (*die)(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
void (*notify_drone_death)(edict_t *self);

float touch_debounce_time; // are all these legit? do we need more/less of them?
float pain_debounce_time;
Expand Down
191 changes: 106 additions & 85 deletions src/gamemodes/invasion.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include "g_local.h"
#include "invasion.h"

#define MAX_ACTIVE_MONSTERS 20
// 70% of the wave needs to be cleared to advance
#define WAVE_CLEAR_THRESHOLD 0.7

//FIXME: need queue that holds all players that are waiting to respawn but all spawns are busy
edict_t *INV_SpawnQue[MAX_CLIENTS];
int invasion_max_playerspawns;
Expand Down Expand Up @@ -56,6 +60,7 @@ void INV_Init(void)
if (!pvm->value || !invasion->value)
return;

memset(&invasion_data, 0, sizeof (struct invdata_s));
INV_InitSpawnQue();
INVASION_OTHERSPAWNS_REMOVED = false;
invasion_difficulty_level = 1;
Expand Down Expand Up @@ -490,8 +495,8 @@ edict_t* INV_SpawnDrone(edict_t* self, edict_t *spawn_point, int index)
}
else if (invasion->value == 2) // hard mode
{
float plog = log2(vrx_get_joined_players() + 1) / log2(4);
mhealth = 1 + 0.1 * invasion_difficulty_level * max(plog, 0);
float plog = log2(vrx_get_joined_players() + 1) / log2(8);
mhealth = 1 + 0.2 * sqrt(invasion_difficulty_level) * max(plog, 0);
}

monster->max_health = monster->health = monster->max_health*mhealth;
Expand Down Expand Up @@ -632,10 +637,12 @@ void INV_OnTimeout(edict_t *self) {
}
// remove monsters from the current wave before spawning the next
if (self->num_monsters_real)
PVM_RemoveAllMonsters(self);
// restart the last wave
if (!was_boss)
vrx_remove_all_monsters(self);

// restart the last wave if we were done spawning
if (!was_boss && self->count == MONSTERSPAWN_STATUS_IDLE) {
invasion_difficulty_level -= 1;
}

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

void INV_OnBeginWave(edict_t *self, int max_monsters) {
invasion_data.limitframe = level.time + TimeFormula();
invasion_data.printedmessage = true;

if (invasion_difficulty_level == 1)
{
if (invasion->value == 1)
Expand All @@ -716,6 +726,7 @@ void INV_OnBeginWave(edict_t *self, int max_monsters) {
G_PrintGreenText(va("Timelimit: %dm %ds.\n", (int)TimeFormula() / 60, (int)TimeFormula() % 60));

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

// check for a boss spawn
INV_BossCheck(self);
Expand Down Expand Up @@ -800,21 +811,93 @@ void INV_SelectMonsterSet(const edict_t* self, int const * * monster_set, int* m
}
}

void INV_Spawnstate_Idle(edict_t *self, const int players) {
// if there's nobody playing, remove all monsters

if (players < 1)
{
// az: reset the current wave to avoid people skipping waves
if (self->num_monsters_real) {
invasion_difficulty_level -= 1;
invasion_data.printedmessage = false;
vrx_remove_all_monsters(self);
}
}
}

qboolean INV_Spawnstate_Working(edict_t *self, const int players, int max_monsters, edict_t *e) {
int SpawnTries = 0, MaxTriesThisFrame = 32;

if (players < 1)
{
return true;
}

// print the message and set the timer the first frame we start working
if (!invasion_data.printedmessage) {
INV_OnBeginWave(self, max_monsters);
INV_SelectMonsterSet(NULL, &invasion_data.monster_set, &invasion_data.monster_set_count);
}

while ((e = INV_GetMonsterSpawn(e))
&& invasion_data.mspawned < max_monsters
&& self->num_monsters_real < MAX_ACTIVE_MONSTERS
&& SpawnTries < MaxTriesThisFrame)
{
//const int* monster_set;
//int monster_set_count;
int pick;
int monster ;

INV_SelectMonsterSet(e, &invasion_data.monster_set, &invasion_data.monster_set_count);
pick = GetRandom(1, invasion_data.monster_set_count) - 1;
monster = invasion_data.monster_set[pick];

SpawnTries++;
if (INV_SpawnDrone(self, e, monster)) // Wait for now
invasion_data.mspawned++;
}

if (invasion_data.mspawned >= max_monsters)
{
// increase the difficulty level for the next wave
invasion_difficulty_level += 1;
invasion_data.printedmessage = 0;
invasion_data.mspawned = 0;
self->count = MONSTERSPAWN_STATUS_IDLE;
//gi.dprintf("invasion level now: %d\n", invasion_difficulty_level);
}
return false;
}

void INV_NotifyMonsterDeath(edict_t * edict) {
invasion_data.remaining_monsters--;
}

void INV_SpawnMonsters(edict_t *self)
{
const int players = vrx_get_joined_players();

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

edict_t *e = NULL;
int SpawnTries = 0, MaxTriesThisFrame = 32;

self->nextthink = level.time + FRAMETIME;

// the level ended, remove monsters
if (level.intermissiontime)
{
if (self->num_monsters_real)
vrx_remove_all_monsters(self);
return;
}

// get the value of all of our monsters (BF flag mult * level * control_cost)
// max_monsters_value = PVM_TotalMonstersValue(self);
// update our drone count
PVM_TotalMonsters(self, true);
vrx_pvm_update_total_owned_monsters(self, true);

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

// Idle State
// we're done spawning
if (self->count == MONSTERSPAWN_STATUS_IDLE)
{
// if there's nobody playing, remove all monsters
if (players < 1)
{
// az: reset the current wave to avoid people skipping waves
if (self->num_monsters_real) {
invasion_difficulty_level -= 1;
invasion_data.printedmessage = false;
PVM_RemoveAllMonsters(self);
}
}

// the level ended, remove monsters
if (level.intermissiontime)
{
if (self->num_monsters_real)
PVM_RemoveAllMonsters(self);
return;
}

// were all monsters eliminated?
if (self->num_monsters_real == 0) {
// start spawning
self->nextthink = level.time + FRAMETIME;
self->count = MONSTERSPAWN_STATUS_WORKING;
return;
}

// were enough monsters eliminated?
if (invasion_data.remaining_monsters <= 0 && !invasion_data.boss) {
// start spawning
self->count = MONSTERSPAWN_STATUS_WORKING;
}

// Check for timeout
// Check for timeout if there are players
if (players >= 1 && invasion_difficulty_level > 1) {
if (invasion_data.limitframe > level.time) // we still got time?
{
self->nextthink = level.time + FRAMETIME;
return;
}
else
{
// Timeout. We go straight to the working state.
INV_OnTimeout(self);
//self->count = MONSTERSPAWN_STATUS_WORKING;
return;
}
}

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

// print the message and set the timer the first frame we start working
if (!invasion_data.printedmessage) {
invasion_data.limitframe = level.time + TimeFormula();
INV_OnBeginWave(self, max_monsters);
invasion_data.printedmessage = true;
INV_SelectMonsterSet(NULL, &invasion_data.monster_set, &invasion_data.monster_set_count);
}

self->nextthink = level.time + FRAMETIME;

while ((e = INV_GetMonsterSpawn(e))
&& invasion_data.mspawned < max_monsters
&& SpawnTries < MaxTriesThisFrame)
{
//const int* monster_set;
//int monster_set_count;
int pick;
int monster ;

INV_SelectMonsterSet(e, &invasion_data.monster_set, &invasion_data.monster_set_count);
pick = GetRandom(1, invasion_data.monster_set_count) - 1;
monster = invasion_data.monster_set[pick];

SpawnTries++;
if (INV_SpawnDrone(self, e, monster)) // Wait for now
invasion_data.mspawned++;
}

if (invasion_data.mspawned >= max_monsters)
{
// increase the difficulty level for the next wave
invasion_difficulty_level += 1;
invasion_data.printedmessage = 0;
invasion_data.mspawned = 0;
self->count = MONSTERSPAWN_STATUS_IDLE;
//gi.dprintf("invasion level now: %d\n", invasion_difficulty_level);
}
// Working State
//gi.dprintf("%d: level: %d max_monsters: %d\n", (int)(level.framenum), invasion_difficulty_level, max_monsters);
// if there's nobody playing, then wait until some join
INV_Spawnstate_Working(self, players, max_monsters, e);
}

void INV_SpawnPlayers(void)
Expand Down
3 changes: 3 additions & 0 deletions src/gamemodes/invasion.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ struct invdata_s
// working monster set
const int* monster_set;
int monster_set_count;
int remaining_monsters;
// default monster set - may be overridden by spawn
const int* default_monster_set;
int default_set_count;
Expand All @@ -18,3 +19,5 @@ struct invdata_s
extern struct invdata_s invasion_data;

int G_GetEntityIndex(edict_t *ent);
void INV_SpawnMonsters(edict_t *self);
void INV_NotifyMonsterDeath(edict_t * edict);

0 comments on commit 2d6ce0c

Please sign in to comment.