1
1
#include "g_local.h"
2
2
#include "invasion.h"
3
3
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
+
4
8
//FIXME: need queue that holds all players that are waiting to respawn but all spawns are busy
5
9
edict_t * INV_SpawnQue [MAX_CLIENTS ];
6
10
int invasion_max_playerspawns ;
@@ -56,6 +60,7 @@ void INV_Init(void)
56
60
if (!pvm -> value || !invasion -> value )
57
61
return ;
58
62
63
+ memset (& invasion_data , 0 , sizeof (struct invdata_s ));
59
64
INV_InitSpawnQue ();
60
65
INVASION_OTHERSPAWNS_REMOVED = false;
61
66
invasion_difficulty_level = 1 ;
@@ -490,8 +495,8 @@ edict_t* INV_SpawnDrone(edict_t* self, edict_t *spawn_point, int index)
490
495
}
491
496
else if (invasion -> value == 2 ) // hard mode
492
497
{
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 );
495
500
}
496
501
497
502
monster -> max_health = monster -> health = monster -> max_health * mhealth ;
@@ -632,10 +637,12 @@ void INV_OnTimeout(edict_t *self) {
632
637
}
633
638
// remove monsters from the current wave before spawning the next
634
639
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 ) {
638
644
invasion_difficulty_level -= 1 ;
645
+ }
639
646
640
647
// increase the difficulty level for the next wave
641
648
//if (invasion->value == 1)
@@ -699,6 +706,9 @@ void INV_ShowLastWaveSummary() {
699
706
}
700
707
701
708
void INV_OnBeginWave (edict_t * self , int max_monsters ) {
709
+ invasion_data .limitframe = level .time + TimeFormula ();
710
+ invasion_data .printedmessage = true;
711
+
702
712
if (invasion_difficulty_level == 1 )
703
713
{
704
714
if (invasion -> value == 1 )
@@ -716,6 +726,7 @@ void INV_OnBeginWave(edict_t *self, int max_monsters) {
716
726
G_PrintGreenText (va ("Timelimit: %dm %ds.\n" , (int )TimeFormula () / 60 , (int )TimeFormula () % 60 ));
717
727
718
728
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 ;
719
730
720
731
// check for a boss spawn
721
732
INV_BossCheck (self );
@@ -800,21 +811,93 @@ void INV_SelectMonsterSet(const edict_t* self, int const * * monster_set, int* m
800
811
}
801
812
}
802
813
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
+
803
877
void INV_SpawnMonsters (edict_t * self )
804
878
{
805
879
const int players = vrx_get_joined_players ();
806
880
807
881
// How many monsters should we spawn?
808
882
// 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 ));
810
884
811
885
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
+ }
813
896
814
897
// get the value of all of our monsters (BF flag mult * level * control_cost)
815
898
// max_monsters_value = PVM_TotalMonstersValue(self);
816
899
// update our drone count
817
- PVM_TotalMonsters (self , true);
900
+ vrx_pvm_update_total_owned_monsters (self , true);
818
901
819
902
//max_monsters = 1;//GHz DEBUG - REMOVE ME!
820
903
//self->nextthink = level.time + FRAMETIME;//GHz DEBUG - REMOVE ME!
@@ -828,99 +911,37 @@ void INV_SpawnMonsters(edict_t *self)
828
911
max_monsters = 6 * (vrx_get_joined_players () - 1 );
829
912
}
830
913
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
+ }
862
919
863
- // Check for timeout
920
+ // Check for timeout if there are players
921
+ if (players >= 1 && invasion_difficulty_level > 1 ) {
864
922
if (invasion_data .limitframe > level .time ) // we still got time?
865
923
{
866
924
self -> nextthink = level .time + FRAMETIME ;
867
- return ;
868
925
}
869
926
else
870
927
{
871
928
// Timeout. We go straight to the working state.
872
929
INV_OnTimeout (self );
873
- //self->count = MONSTERSPAWN_STATUS_WORKING;
874
- return ;
875
930
}
876
931
}
877
932
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 )
882
936
{
883
- self -> nextthink = level . time + FRAMETIME ;
937
+ INV_Spawnstate_Idle ( self , players ) ;
884
938
return ;
885
939
}
886
940
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 );
924
945
}
925
946
926
947
void INV_SpawnPlayers (void )
0 commit comments