From b578491e12397e093d1801efd41096cadf911cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 3 Oct 2024 20:54:24 +0200 Subject: [PATCH 01/62] First commit, the start of a new FUN gamemode. --- Posto-Stuff-ReadmePLZ.txt | 11 ++ code/cgame/cg_main.cpp | 2 +- code/game/NPC_spawn.cpp | 382 ++++++++++++++++++++++++++++++++++++++ code/game/g_itemLoad.cpp | 1 + code/game/g_spawn.cpp | 107 +++++++++++ code/game/game.vcxproj | 8 +- code/starwars.vcxproj | 10 +- code/win32/winquake.res | Bin 4552 -> 5480 bytes 8 files changed, 511 insertions(+), 10 deletions(-) create mode 100644 Posto-Stuff-ReadmePLZ.txt diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt new file mode 100644 index 00000000..ed67f83e --- /dev/null +++ b/Posto-Stuff-ReadmePLZ.txt @@ -0,0 +1,11 @@ +Findings on this Randomizer : +- Friendly and neutral NPC carry necessary items (for exemple, the key on kejim_base). +- Some NPC have to be locked, otherwise, we might get undefined behavior in cutscene or else. +- In ns_streets, no matter which npc (except the ones in the little arena) are forced on a path. +- IMPOSSIBLE to start a new game. The game just crashes, no + +TODO : +- Lock all necessarry NPC per map (right now thinking about undercity and assembly, to open doors). +- Fixing G_FindConfigstringIndex (very hard). +- Stop the crashes (very hard). +- Maybe add some kind of items randomize ? Except the necessarry ones ofc. \ No newline at end of file diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 37b2e7f6..4dcad20f 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -1483,7 +1483,7 @@ static void CG_RegisterGraphics( void ) { CG_LoadingString( cgs.mapname ); cgi_R_LoadWorldMap( cgs.mapname ); - + cg.loadLCARSStage = 4; CG_LoadingString( "game media shaders" ); diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index e24ff1ec..0bca8280 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2783,6 +2783,388 @@ void SP_NPC_Droid_Protocol( gentity_t *self) NPC_Protocol_Precache(); } +// The Posto is for faster search so I know what I edited +void SP_NPC_Spawn_Random(gentity_t* self) +{ + // Pas besoin de srand puisqu'il ets call déjà sur g_main.cpp (???????) + // Modulo de 49 car il y a 49 entités si j'ai bien compté. +1 pour skip Kyle, même si avoir 2 Kyle n'est potentiellement pas un problème. + int who = rand() % 50 ; + switch (who) + { + case 0: + SP_NPC_Kyle(self); + break; + case 1: + SP_NPC_Lando(self); + break; + case 2: + SP_NPC_Jan(self); + break; + case 3: + SP_NPC_Luke(self); + break; + case 4: // Elle a une IA au moins ? + SP_NPC_MonMothma(self); + break; + case 5: + SP_NPC_Tavion(self); + break; + case 6: // Il a une IA au moins ? + SP_NPC_Reelo(self); + break; + case 7: + SP_NPC_Galak(self); + break; + case 8: + SP_NPC_Desann(self); + break; + case 9: // Il a une IA au moins ? + SP_NPC_Bartender(self); + break; + case 10: + SP_NPC_MorganKatarn(self); + break; + case 11: + SP_NPC_Jedi(self); + break; + case 12: + SP_NPC_Prisoner(self); + break; + case 13: + SP_NPC_Rebel(self); + break; + case 14: // Le classique + SP_NPC_Stormtrooper(self); + break; + case 15: + SP_NPC_StormtrooperOfficer(self); + break; + case 16: + SP_NPC_Tie_Pilot(self); + break; + case 17: // C'est qui ? + SP_NPC_Ugnaught(self); + break; + case 18: // C'est qui ? + SP_NPC_Gran(self); + break; + case 19: + SP_NPC_Rodian(self); + break; + case 20: + SP_NPC_Weequay(self); + break; + case 21: + SP_NPC_Trandoshan(self); + break; + case 22: + SP_NPC_SwampTrooper(self); + break; + case 23: + SP_NPC_Imperial(self); + break; + case 24: + SP_NPC_ImpWorker(self); + break; + case 25: + SP_NPC_BespinCop(self); + break; + case 26: + SP_NPC_Reborn(self); + break; + case 27: + SP_NPC_ShadowTrooper(self); + break; + case 28: // Attention + SP_NPC_Monster_Murjj(self); + //SP_NPC_Stormtrooper(self); + break; + case 29: // Attention + SP_NPC_Monster_Swamp(self); + //SP_NPC_Stormtrooper(self); + break; + case 30: // Attention + SP_NPC_Monster_Howler(self); + //SP_NPC_Stormtrooper(self); + break; + case 31: + SP_NPC_MineMonster(self); + break; + case 32: // Attention + SP_NPC_Monster_Claw(self); + //SP_NPC_Stormtrooper(self); + break; + case 33: // Attention + SP_NPC_Monster_Glider(self); + //SP_NPC_Stormtrooper(self); + break; + case 34: // Attention + SP_NPC_Monster_Flier2(self); + //SP_NPC_Stormtrooper(self); + break; + case 35: // Attention + SP_NPC_Monster_Lizard(self); + //SP_NPC_Stormtrooper(self); + break; + case 36: // Attention + SP_NPC_Monster_Fish(self); + //SP_NPC_Stormtrooper(self); + break; + case 37: + SP_NPC_Droid_Interrogator(self); + break; + case 38: + SP_NPC_Droid_Probe(self); + break; + case 39: + SP_NPC_Droid_Mark1(self); + break; + case 40: + SP_NPC_Droid_Mark2(self); + break; + case 41: // Attention + SP_NPC_Droid_ATST(self); + //SP_NPC_Stormtrooper(self); + break; + case 42: + SP_NPC_Droid_Seeker(self); + break; + case 43: + SP_NPC_Droid_Remote(self); + break; + case 44: + SP_NPC_Droid_Sentry(self); + break; + case 45: + SP_NPC_Droid_Gonk(self); + break; + case 46: + SP_NPC_Droid_Mouse(self); + break; + case 47: + SP_NPC_Droid_R2D2(self); + break; + case 48: + SP_NPC_Droid_R5D2(self); + break; + case 49: + SP_NPC_Droid_Protocol(self); + break; + default: // Secours + SP_NPC_Stormtrooper(self); + break; + } +} +void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle +{ + string mapname = level.mapname; // It works, just need to do a list of NPC to lock and everything + SP_NPC_Kyle(self); +} +void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando +{ + SP_NPC_Lando(self); +} +void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan +{ + SP_NPC_Jan(self); +} +void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke +{ + SP_NPC_Luke(self); +} +void SP_NPC_MonMothma_Random(gentity_t* self) // MonMothma should always spawn as MonMothma +{ + SP_NPC_MonMothma(self); +} +void SP_NPC_Tavion_Random(gentity_t* self) // Tavion should always spawn as Tavion +{ + SP_NPC_Tavion(self); +} +void SP_NPC_Reelo_Random(gentity_t* self) // Reelo should always spawn as Reelo +{ + SP_NPC_Reelo(self); +} +void SP_NPC_Galak_Random(gentity_t* self) // Galak should always spawn as Galak +{ + SP_NPC_Galak(self); +} +void SP_NPC_Desann_Random(gentity_t* self) // Desann should always spawn as Desann +{ + SP_NPC_Desann(self); +} +void SP_NPC_Bartender_Random(gentity_t* self) // Bartender should always spawn as Bartender +{ + SP_NPC_Bartender(self); +} +void SP_NPC_MorganKatarn_Random(gentity_t* self) // Morgarn should always spawn as Morgarn +{ + SP_NPC_MorganKatarn(self); +} +void SP_NPC_Jedi_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Prisoner_Random(gentity_t* self) // Prisoners should spawn as themselves +{ + SP_NPC_Prisoner(self); +} +void SP_NPC_Rebel_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Stormtrooper_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_StormtrooperOfficer_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Tie_Pilot_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaught +{ + SP_NPC_Ugnaught(self); +} +void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Rodian_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Weequay_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Trandoshan_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_SwampTrooper_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Imperial_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_ImpWorker_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_BespinCop_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Reborn_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_ShadowTrooper_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Murjj_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Swamp_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Howler_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Claw_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Glider_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Flier2_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Lizard_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Monster_Fish_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_MineMonster_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Interrogator_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Probe_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Mark1_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Mark2_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_ATST_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Seeker_Random(gentity_t* self) // Seekers should always be seekers, at least in speedruns +{ + SP_NPC_Droid_Seeker(self); +} +void SP_NPC_Droid_Remote_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Sentry_Random(gentity_t* self) // Who is that ? +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Gonk_Random(gentity_t* self) +{ + SP_NPC_Spawn_Random(self); +} +void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse +{ + SP_NPC_Droid_Mouse(self); +} +void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self +{ + SP_NPC_Droid_R2D2(self); +} +void SP_NPC_Droid_R5D2_Random(gentity_t* self) +{ + SP_NPC_Droid_R5D2(self); +} +void SP_NPC_Droid_Protocol_Random(gentity_t* self) +{ + SP_NPC_Droid_Protocol(self); +} + + + + + + + + + //NPC console commands /* diff --git a/code/game/g_itemLoad.cpp b/code/game/g_itemLoad.cpp index 94f6a76f..753f9719 100644 --- a/code/game/g_itemLoad.cpp +++ b/code/game/g_itemLoad.cpp @@ -206,6 +206,7 @@ static void IT_Name(const char **holdBuf) { itemNum = ITM_BATTERY_PICKUP; } + // Posto : TODO else if (!Q_stricmp(tokenStr,"ITM_SEEKER_PICKUP")) itemNum = ITM_SEEKER_PICKUP; else if (!Q_stricmp(tokenStr,"ITM_SHIELD_PICKUP")) diff --git a/code/game/g_spawn.cpp b/code/game/g_spawn.cpp index 70143d7c..406cf966 100644 --- a/code/game/g_spawn.cpp +++ b/code/game/g_spawn.cpp @@ -465,6 +465,59 @@ void SP_NPC_Droid_R2D2( gentity_t *self ); void SP_NPC_Droid_R5D2( gentity_t *self ); void SP_NPC_Droid_Protocol( gentity_t *self ); +// Posto : Ajouter toutes les fonctions qui permettent de faire spawn en random ou non +void SP_NPC_Spawn_Random(gentity_t* self); +void SP_NPC_Kyle_Random(gentity_t* self); +void SP_NPC_Lando_Random(gentity_t* self); +void SP_NPC_Jan_Random(gentity_t* self); +void SP_NPC_Luke_Random(gentity_t* self); +void SP_NPC_MonMothma_Random(gentity_t* self); +void SP_NPC_Tavion_Random(gentity_t* self); +void SP_NPC_Reelo_Random(gentity_t* self); +void SP_NPC_Galak_Random(gentity_t* self); +void SP_NPC_Desann_Random(gentity_t* self); +void SP_NPC_Bartender_Random(gentity_t* self); +void SP_NPC_MorganKatarn_Random(gentity_t* self); +void SP_NPC_Jedi_Random(gentity_t* self); +void SP_NPC_Prisoner_Random(gentity_t* self); +void SP_NPC_Rebel_Random(gentity_t* self); +void SP_NPC_Stormtrooper_Random(gentity_t* self); +void SP_NPC_StormtrooperOfficer_Random(gentity_t* self); +void SP_NPC_Tie_Pilot_Random(gentity_t* self); +void SP_NPC_Ugnaught_Random(gentity_t* self); +void SP_NPC_Gran_Random(gentity_t* self); +void SP_NPC_Rodian_Random(gentity_t* self); +void SP_NPC_Weequay_Random(gentity_t* self); +void SP_NPC_Trandoshan_Random(gentity_t* self); +void SP_NPC_SwampTrooper_Random(gentity_t* self); +void SP_NPC_Imperial_Random(gentity_t* self); +void SP_NPC_ImpWorker_Random(gentity_t* self); +void SP_NPC_BespinCop_Random(gentity_t* self); +void SP_NPC_Reborn_Random(gentity_t* self); +void SP_NPC_ShadowTrooper_Random(gentity_t* self); +void SP_NPC_Monster_Murjj_Random(gentity_t* self); +void SP_NPC_Monster_Swamp_Random(gentity_t* self); +void SP_NPC_Monster_Howler_Random(gentity_t* self); +void SP_NPC_Monster_Claw_Random(gentity_t* self); +void SP_NPC_Monster_Glider_Random(gentity_t* self); +void SP_NPC_Monster_Flier2_Random(gentity_t* self); +void SP_NPC_Monster_Lizard_Random(gentity_t* self); +void SP_NPC_Monster_Fish_Random(gentity_t* self); +void SP_NPC_MineMonster_Random(gentity_t* self); +void SP_NPC_Droid_Interrogator_Random(gentity_t* self); +void SP_NPC_Droid_Probe_Random(gentity_t* self); +void SP_NPC_Droid_Mark1_Random(gentity_t* self); +void SP_NPC_Droid_Mark2_Random(gentity_t* self); +void SP_NPC_Droid_ATST_Random(gentity_t* self); +void SP_NPC_Droid_Seeker_Random(gentity_t* self); +void SP_NPC_Droid_Remote_Random(gentity_t* self); +void SP_NPC_Droid_Sentry_Random(gentity_t* self); +void SP_NPC_Droid_Gonk_Random(gentity_t* self); +void SP_NPC_Droid_Mouse_Random(gentity_t* self); +void SP_NPC_Droid_R2D2_Random(gentity_t* self); +void SP_NPC_Droid_R5D2_Random(gentity_t* self); +void SP_NPC_Droid_Protocol_Random(gentity_t* self); + void SP_waypoint (gentity_t *ent); void SP_waypoint_small (gentity_t *ent); void SP_waypoint_navgoal (gentity_t *ent); @@ -596,6 +649,7 @@ spawn_t spawns[] = { //new NPC ents {"NPC_spawner", SP_NPC_spawner}, + /* {"NPC_Kyle", SP_NPC_Kyle }, {"NPC_Lando", SP_NPC_Lando }, {"NPC_Jan", SP_NPC_Jan }, @@ -646,6 +700,59 @@ spawn_t spawns[] = { {"NPC_Droid_R2D2", SP_NPC_Droid_R2D2 }, {"NPC_Droid_R5D2", SP_NPC_Droid_R5D2 }, {"NPC_Droid_Protocol", SP_NPC_Droid_Protocol }, + */ + + // Posto + { "NPC_Kyle", SP_NPC_Kyle_Random }, + { "NPC_Lando", SP_NPC_Lando_Random }, + { "NPC_Jan", SP_NPC_Jan_Random }, + { "NPC_Luke", SP_NPC_Luke_Random }, + { "NPC_MonMothma", SP_NPC_MonMothma_Random }, + { "NPC_Tavion", SP_NPC_Tavion_Random }, + { "NPC_Reelo", SP_NPC_Reelo_Random }, + { "NPC_Galak", SP_NPC_Galak_Random }, + { "NPC_Desann", SP_NPC_Desann_Random }, + { "NPC_Bartender", SP_NPC_Bartender_Random }, + { "NPC_MorganKatarn", SP_NPC_MorganKatarn_Random }, + { "NPC_Jedi", SP_NPC_Jedi_Random }, + { "NPC_Prisoner", SP_NPC_Prisoner_Random }, + { "NPC_Rebel", SP_NPC_Rebel_Random }, + { "NPC_Stormtrooper", SP_NPC_Stormtrooper_Random }, + { "NPC_StormtrooperOfficer", SP_NPC_StormtrooperOfficer_Random }, + { "NPC_Tie_Pilot", SP_NPC_Tie_Pilot_Random }, + { "NPC_Ugnaught", SP_NPC_Ugnaught_Random }, + { "NPC_Gran", SP_NPC_Gran_Random }, + { "NPC_Rodian", SP_NPC_Rodian_Random }, + { "NPC_Weequay", SP_NPC_Weequay_Random }, + { "NPC_Trandoshan", SP_NPC_Trandoshan_Random }, + { "NPC_SwampTrooper", SP_NPC_SwampTrooper_Random }, + { "NPC_Imperial", SP_NPC_Imperial_Random }, + { "NPC_ImpWorker", SP_NPC_ImpWorker_Random }, + { "NPC_BespinCop", SP_NPC_BespinCop_Random }, + { "NPC_Reborn", SP_NPC_Reborn_Random }, + { "NPC_ShadowTrooper", SP_NPC_ShadowTrooper_Random }, + { "NPC_Monster_Murjj", SP_NPC_Monster_Murjj_Random }, + { "NPC_Monster_Swamp", SP_NPC_Monster_Swamp_Random }, + { "NPC_Monster_Howler", SP_NPC_Monster_Howler_Random }, + { "NPC_MineMonster", SP_NPC_MineMonster_Random }, + { "NPC_Monster_Claw", SP_NPC_Monster_Claw_Random }, + { "NPC_Monster_Glider", SP_NPC_Monster_Glider_Random }, + { "NPC_Monster_Flier2", SP_NPC_Monster_Flier2_Random }, + { "NPC_Monster_Lizard", SP_NPC_Monster_Lizard_Random }, + { "NPC_Monster_Fish", SP_NPC_Monster_Fish_Random }, + { "NPC_Droid_Interrogator", SP_NPC_Droid_Interrogator_Random }, + { "NPC_Droid_Probe", SP_NPC_Droid_Probe_Random }, + { "NPC_Droid_Mark1", SP_NPC_Droid_Mark1_Random }, + { "NPC_Droid_Mark2", SP_NPC_Droid_Mark2_Random }, + { "NPC_Droid_ATST", SP_NPC_Droid_ATST_Random }, + { "NPC_Droid_Seeker", SP_NPC_Droid_Seeker_Random }, + { "NPC_Droid_Remote", SP_NPC_Droid_Remote_Random }, + { "NPC_Droid_Sentry", SP_NPC_Droid_Sentry_Random }, + { "NPC_Droid_Gonk", SP_NPC_Droid_Gonk_Random }, + { "NPC_Droid_Mouse", SP_NPC_Droid_Mouse_Random }, + { "NPC_Droid_R2D2", SP_NPC_Droid_R2D2_Random }, + { "NPC_Droid_R5D2", SP_NPC_Droid_R5D2_Random }, + { "NPC_Droid_Protocol", SP_NPC_Droid_Protocol_Random }, {"waypoint", SP_waypoint}, {"waypoint_small", SP_waypoint_small}, diff --git a/code/game/game.vcxproj b/code/game/game.vcxproj index 14ac6f91..f2f7bc5a 100644 --- a/code/game/game.vcxproj +++ b/code/game/game.vcxproj @@ -25,22 +25,22 @@ DynamicLibrary - v142 + v143 false DynamicLibrary - v142 + v143 false DynamicLibrary - v142 + v143 false DynamicLibrary - v142 + v143 false diff --git a/code/starwars.vcxproj b/code/starwars.vcxproj index 321f484f..70ee0baa 100644 --- a/code/starwars.vcxproj +++ b/code/starwars.vcxproj @@ -29,26 +29,26 @@ Application - v142 + v143 Application - v142 + v143 false Application - v142 + v143 false Application - v142 + v143 false Application - v142 + v143 false diff --git a/code/win32/winquake.res b/code/win32/winquake.res index 9ef83656f29576ba9800abde862da926d15d8eee..6f58d2668518e50cff2b2f6aabe506a61fe6ff07 100644 GIT binary patch delta 943 zcmaizO)mpc6o%hcBS9jpEG$eyB0;1?B*aF1BtD{zO1Dx~HPo~*Q(v3$ldL87eucH2 ze}L!Q8Y$YC=H5BI=RNOv&pCIV$6u!&o`>W69?6sR@iD|oVM$r_Wt_ow-?PA8R6&RA z8`{U(QcipP-(ugyw&yAH_AXg`iz9iDe4Q9!;=y#!OIk691x31)uRvAkeAQHeI?##g zz#h{UnAHMn$-R%*Me0$`*T7uxtALLba-MTsRmWF?tEO8m%R_icR}SZqu?~BrYsDqt z6{n`yM%Vxx5V*(N$nEJyys9!(KIA?Ee5eD`Spj7iccL+bCWWoT7UHpj8;atu07IIp zCXO-?4`&@a!ZNL%wmCfp?IEPec^PS;^B0tNi54}`mZ%8+@>`Gr<}^ce_QxKZV@ACM zn&QX>1yI-8YTwq5=8FZU41$Mg1iI zJ&2^WCc8DPGo2$iMA$4sZ&=cb28qohv`!zJ^e>`B=AX>B0KCHQ_)m+)1+v!u4F28V qPVFVH)>$dO9V;`D`hC48aZboSjsx6w=|WmxLR;%1;oxI@$b15z*ODs$ delta 7 OcmaE%bwYW=2|)l4fCGmB From 696ef083d487085cbe1bc578fa21969aab0a5629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 3 Oct 2024 21:44:17 +0200 Subject: [PATCH 02/62] New branch only for debug, tests and findings to keep master cleaner than my mess. --- Posto-Stuff-ReadmePLZ.txt | 8 +- code/base/jk2config.cfg | 404 +++++++++++++++++++++++--------------- 2 files changed, 251 insertions(+), 161 deletions(-) diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index ed67f83e..ce42b7fc 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -2,10 +2,14 @@ Findings on this Randomizer : - Friendly and neutral NPC carry necessary items (for exemple, the key on kejim_base). - Some NPC have to be locked, otherwise, we might get undefined behavior in cutscene or else. - In ns_streets, no matter which npc (except the ones in the little arena) are forced on a path. -- IMPOSSIBLE to start a new game. The game just crashes, no +- IMPOSSIBLE to start a new game. TODO : - Lock all necessarry NPC per map (right now thinking about undercity and assembly, to open doors). - Fixing G_FindConfigstringIndex (very hard). - Stop the crashes (very hard). -- Maybe add some kind of items randomize ? Except the necessarry ones ofc. \ No newline at end of file +- Maybe add some kind of items randomize ? Except the necessarry ones ofc. + +Crash : common.cpp, line 296 +It happens because of G_FindConfigstringIndex each time it seems. +I don't know how to fix that, because if it's truly this case every time, it could be a cool mod :/ \ No newline at end of file diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index b8a8a752..bb1ed637 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -1,19 +1,20 @@ // generated by Star Wars Jedi Outcast, do not modify unbindall bind SHIFT "+speed" -bind CTRL "+use" -bind ALT "+altattack" -bind TAB "datapad" +bind CTRL "+movedown" +bind ALT "force_pull" +bind TAB "cg_thirdperson !" bind ENTER "invuse" -bind KP_PGDN "use_seeker" +bind KP_INS "vstr svfps1" +bind KP_DOWNARROW "use_seeker" bind KP_LEFTARROW "use_lightamp_goggles" bind KP_5 "use_sentry" -bind F1 "force_throw" -bind F2 "force_pull" +bind F1 "save quik*" +bind F2 "load quik" bind F3 "force_speed" bind F4 "force_distract" bind SPACE "+moveup" -bind , "+moveleft" +bind ) "invnext" bind - "weapon 0" bind . "+moveright" bind / "+mlook" @@ -27,24 +28,25 @@ bind 6 "weapon 6" bind 7 "weapon 7" bind 8 "weapon 8" bind 9 "weapon 9" -bind = "screenshot silent" -bind A "+moveleft" +bind A "force_throw" bind B "use_bacta" bind C "+movedown" bind D "+moveright" bind E "+use" -bind F "+useforce" +bind F "+strafe" bind G "zoom" bind L "saberAttackCycle" bind M "datapad" +bind N "use_seeker" +bind O "centerview" bind P "cg_thirdperson !" -bind Q "weapprev" +bind Q "+moveleft" bind R "weapnext" bind S "+back" bind V "+strafe" -bind W "+forward" -bind X "forcenext" -bind Z "forceprev" +bind W "soundstop" +bind X "vid_restart" +bind Z "+forward" bind [ "invprev" bind \ "weapongrabbed" bind ] "invnext" @@ -58,163 +60,247 @@ bind MWHEELDOWN "weapnext" bind MOUSE1 "+attack" bind MOUSE2 "+altattack" bind PGUP "+lookup" -bind F9 "load quik" bind F10 "uimenu ingameloadmenu" bind F11 "uimenu ingamesavemenu" -bind F12 "save quik*" bind END "centerview" bind PGDN "+lookdown" bind MOUSE3 "zoom" -bind UPARROW "+forward" +bind MOUSE5 "force_throw" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -bind JOY0 "+attack" -bind JOY1 "+attack" +seta r_weatherScale "1" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta d_slowmodeath "0" +seta ui_iscensored "0" +seta g_speedFactorLanding "1.0" +seta g_saber_color "yellow" +seta g_saberAutoAim "1" +seta g_saberAnimSpeed "1" +seta g_saberMoveSpeed "1" +seta g_saberRealisticCombat "0" +seta g_saberAutoBlocking "1" +seta g_dismemberProbabilities "1" +seta g_dismemberment "3" +seta cg_strafeHelperColorSpeedA "0.9" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperCenter "1" +seta cg_drawStrafeHelper "0" +seta cg_speedColorA "0.9" +seta cg_speedColorB "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorR "1.0" +seta cg_speedY "75" +seta cg_speedX "0" +seta cg_speedScale "0.9" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperY "0" +seta cg_jumpHelperX "0" +seta cg_drawJumpHelper "0" +seta cg_drawOverbounceInfo "0" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSecrets "0" +seta cg_reliableAnimSounds "1" seta cg_missionInfoCentered "1" -seta ui_r_glCustom "4" -seta r_overBrightBits "1" -seta com_maxfps "85" -seta sp_language "0" -seta in_midi "0" -seta in_midiport "1" -seta in_midichannel "1" -seta in_mididevice "0" -seta in_mouse "-1" -seta in_joystick "1" -seta in_joyBallScale "0.02" -seta joy_threshold "0.15" -seta js_ffmult "3.0" -seta joy_xbutton "1" -seta joy_ybutton "0" -seta k_language "american" -seta use_ff "1" -seta ff_defaultTension "1" -seta conAlpha "1.6" -seta panoNumShots "10" -seta cl_yawspeed "140" -seta cl_pitchspeed "140" -seta cl_anglespeedkey "1.5" -seta cl_maxpackets "30" -seta cl_packetdup "1" -seta cl_run "1" -seta sensitivity "5" -seta cl_mouseAccel "0" -seta cl_freelook "1" -seta cl_ingameVideo "1" -seta cl_VideoQuality "0" -seta cg_autoswitch "1" -seta m_pitch "0.022" -seta m_yaw "0.022" -seta m_forward "0.25" -seta m_side "0.25" -seta m_filter "0" -seta name "Kyle" -seta snaps "20" -seta sex "male" -seta handicap "100" -seta r_allowExtensions "1" -seta r_ext_compress_textures "1" -seta r_ext_compress_lightmaps "0" -seta r_ext_preferred_tc_method "0" -seta r_ext_gamma_control "1" -seta r_ext_multitexture "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_texture_env_add "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_picmip "1" -seta r_detailtextures "1" -seta r_texturebits "0" -seta r_texturebitslm "0" -seta r_colorbits "0" -seta r_stereo "0" -seta r_stencilbits "8" -seta r_depthbits "0" -seta r_ignorehwgamma "0" -seta r_mode "3" -seta r_customwidth "1600" -seta r_customheight "768" -seta r_customaspect "2" -seta r_simpleMipMaps "1" -seta r_vertexLight "0" -seta r_subdivisions "4" -seta r_ignoreFastPath "1" -seta r_intensity "1" -seta r_lodCurveError "250" -seta r_lodbias "0" -seta r_flares "1" -seta r_lodscale "10" -seta r_ignoreGLErrors "1" -seta r_fastsky "0" -seta r_drawSun "0" -seta r_dynamiclight "1" -seta r_dlightBacks "1" -seta r_finish "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_swapInterval "0" -seta r_gamma "1" -seta r_facePlaneCull "1" -seta r_primitives "0" -seta r_showtriscolor "0" -seta cg_shadows "1" -seta r_modelpoolmegs "20" -seta r_lastValidRenderer "GeForce2 MX/AGP/SSE2" -seta vid_xpos "7" -seta vid_ypos "1" -seta s_volume "0.546875" -seta s_volumeVoice "1.0" -seta s_musicvolume "0.460938" -seta s_separation "0.5" -seta s_khz "22" -seta s_allowDynamicMusic "1" -seta s_mixahead "0.2" -seta s_mixPreStep "0.05" -seta s_mp3overhead "31760" -seta s_UseOpenAL "1" -seta s_soundpoolmegs "25" -seta cg_drawCrosshair "1" -seta cg_marks "1" -seta ui_menuFiles "ui/menus.txt" -seta ui_smallFont "0.25" -seta ui_bigFont "0.4" -seta cg_hudFiles "ui/jk2hud.txt" -seta cm_playerCurveClip "1" -seta cg_drawGun "1" -seta cg_stereoSeparation "0.4" -seta cg_draw2D "1" -seta cg_drawStatus "1" -seta cg_drawTimer "0" -seta cg_drawFPS "0" -seta cg_drawSnapshot "0" -seta cg_drawAmmoWarning "1" -seta cg_dynamicCrosshair "1" +seta cg_bobroll "0.002" +seta cg_bobpitch "0.002" +seta cg_bobup "0.005" +seta cg_runroll "0.005" +seta cg_runpitch "0.002" +seta cg_simpleItems "0" +seta cg_crosshairY "0" +seta cg_crosshairX "0" +seta cg_crosshairSize "24" seta cg_crosshairIdentifyTarget "1" +seta cg_dynamicCrosshair "1" +seta cg_drawAmmoWarning "1" +seta cg_drawSnapshot "0" +seta cg_drawServerFPS "1" +seta cg_drawFPS "1" +seta cg_drawTimer "1" +seta cg_drawStatus "1" +seta cg_draw2D "1" +seta cg_stereoSeparation "0.4" +seta cg_drawGun "1" +seta cm_playerCurveClip "1" seta cg_crosshairForceHint "1" -seta cg_crosshairSize "24" -seta cg_crosshairX "0" -seta cg_crosshairY "0" -seta cg_simpleItems "0" -seta cg_runpitch "0.002" -seta cg_runroll "0.005" -seta cg_bobup "0.005" -seta cg_bobpitch "0.002" -seta cg_bobroll "0.002" -seta cg_saberAutoThird "1" +seta g_spskill "0" +seta cg_drawSpeed "0" seta cg_gunAutoFirst "1" -seta cg_reliableAnimSounds "1" -seta g_spskill "1" -seta g_dismemberment "3" -seta g_dismemberProbabilities "0" +seta cg_saberAutoThird "0" seta g_subtitles "2" -seta g_saberAutoBlocking "1" -seta g_saberRealisticCombat "0" -seta g_saberMoveSpeed "1" -seta g_saberAnimSpeed "1" -seta g_saberAutoAim "1" -seta ui_iscensored "0" -seta d_slowmodeath "3" -seta s_language "espanoles" -seta r_weatherScale "1" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta ui_r_glCustom "4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_bigFont "0.4" +seta ui_smallFont "0.25" +seta ui_menuFiles "ui/menus.txt" +seta cg_marks "1" +seta cg_drawCrosshair "1" seta ff_delay "40" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta use_ff "1" +seta s_soundpoolmegs "25" +seta s_UseOpenAL "0" +seta s_mp3overhead "31756" +seta s_language "francais" +seta s_mixPreStep "0.05" +seta s_mixahead "0.2" +seta s_allowDynamicMusic "1" +seta s_khz "22" +seta s_separation "0.5" +seta s_musicvolume "0.031250" +seta s_volumeVoice "0.070312" +seta s_volume "0.085938" +seta vid_ypos "0" +seta vid_xpos "0" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta r_modelpoolmegs "20" +seta cg_shadows "0" +seta r_showtriscolor "0" +seta r_primitives "0" +seta r_facePlaneCull "1" +seta r_gamma "1.359375" +seta r_swapInterval "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_finish "0" +seta r_dlightBacks "1" +seta r_dynamiclight "1" +seta r_drawSun "0" +seta r_fastsky "0" +seta r_ignoreGLErrors "1" +seta r_lodscale "10" +seta r_flares "1" +seta r_lodbias "0" +seta r_lodCurveError "250" +seta r_intensity "1" +seta r_ignoreFastPath "1" +seta r_subdivisions "4" +seta r_vertexLight "0" +seta r_simpleMipMaps "1" +seta r_customaspect "1" +seta r_customheight "1024" +seta r_customwidth "1600" seta r_fullscreen "0" +seta r_mode "8" +seta r_ignorehwgamma "0" +seta r_overBrightBits "1" +seta r_depthbits "24" +seta r_stencilbits "8" +seta r_stereo "0" +seta r_colorbits "32" +seta r_texturebitslm "0" +seta r_texturebits "0" +seta r_detailtextures "1" +seta r_picmip "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_ext_texture_env_add "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_multitexture "1" +seta r_ext_gamma_control "1" +seta r_ext_preferred_tc_method "0" +seta r_ext_compress_lightmaps "0" +seta r_ext_compress_textures "1" +seta r_allowExtensions "1" +seta handicap "100" +seta sex "male" +seta snaps "20" +seta name "Kyle" +seta m_filter "0" +seta m_side "0.25" +seta m_forward "0.25" +seta m_yaw "0.022" +seta m_pitch "0.022" +seta cg_autoswitch "0" +seta cl_VideoQuality "0" +seta cl_ingameVideo "1" +seta cl_freelook "1" +seta cl_mouseAccel "0" +seta sensitivity "5" +seta cl_run "1" +seta cl_packetdup "1" +seta cl_maxpackets "30" +seta cl_anglespeedkey "1.5" +seta cl_pitchspeed "140" +seta cl_yawspeed "140" +seta panoNumShots "10" +seta conAlpha "1.6" +seta sv_timedCheckpointMaxZ "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinX "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeIL "0" +seta joy_ybutton "0" +seta joy_xbutton "1" +seta js_ffmult "3.0" +seta joy_threshold "0.15" +seta in_joyBallScale "0.02" +seta in_joystick "0" +seta in_mouse_raw "1" +seta in_mouse "-1" +seta in_mididevice "0" +seta in_midichannel "1" +seta in_midiport "1" +seta in_midi "0" +seta sp_language "1" +seta com_maxfps "125" From f332aef1633f02a52f42bbb0895497dfbf8adaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 4 Oct 2024 09:47:37 +0200 Subject: [PATCH 03/62] Pushing limits to authorize more unique entities to spawn. Thanks to Amber idea. --- Posto-Stuff-ReadmePLZ.txt | 6 +++++- code/base/jk2config.cfg | 6 +++--- code/game/NPC_spawn.cpp | 2 +- code/game/q_shared.h | 9 ++++++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index ce42b7fc..af426794 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -12,4 +12,8 @@ TODO : Crash : common.cpp, line 296 It happens because of G_FindConfigstringIndex each time it seems. -I don't know how to fix that, because if it's truly this case every time, it could be a cool mod :/ \ No newline at end of file +I don't know how to fix that, because if it's truly this case every time, it could be a cool mod :/ +q_shared : upped the max sounds and models. + +For items : +classname : item_bacta, origin : X,Y,Z \ No newline at end of file diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index bb1ed637..303b48f1 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -205,9 +205,9 @@ seta s_mixahead "0.2" seta s_allowDynamicMusic "1" seta s_khz "22" seta s_separation "0.5" -seta s_musicvolume "0.031250" -seta s_volumeVoice "0.070312" -seta s_volume "0.085938" +seta s_musicvolume "0.023438" +seta s_volumeVoice "0.062500" +seta s_volume "0.054688" seta vid_ypos "0" seta vid_xpos "0" seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 0bca8280..98e0a74a 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2950,7 +2950,7 @@ void SP_NPC_Spawn_Random(gentity_t* self) case 49: SP_NPC_Droid_Protocol(self); break; - default: // Secours + default: // Secours SP_NPC_Stormtrooper(self); break; } diff --git a/code/game/q_shared.h b/code/game/q_shared.h index 7867ef7e..d476738a 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1165,9 +1165,11 @@ typedef struct { #define ENTITYNUM_WORLD (MAX_GENTITIES-2) #define ENTITYNUM_MAX_NORMAL (MAX_GENTITIES-2) +//#define MAX_MODELS 256 // these are sent over the net as 8 bits +//#define MAX_SOUNDS 256 // so they cannot be blindly increased -#define MAX_MODELS 256 // these are sent over the net as 8 bits -#define MAX_SOUNDS 256 // so they cannot be blindly increased +#define MAX_MODELS 512 // Posto : For the Randomizer, we might need to increase it. +#define MAX_SOUNDS 512 // Same for that #ifdef _IMMERSION #define MAX_FORCES 96 @@ -1185,7 +1187,8 @@ Ghoul2 Insert Start Ghoul2 Insert End */ -#define MAX_CONFIGSTRINGS 1024 +//#define MAX_CONFIGSTRINGS 1024 +#define MAX_CONFIGSTRINGS 2048 // Posto : we might need to double this, I understand if we have performance issue // these are the only configstrings that the system reserves, all the // other ones are strictly for servergame to clientgame communication From 8c499b353f7110236f241b1b3359c58b6b2ab605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 4 Oct 2024 17:44:19 +0200 Subject: [PATCH 04/62] Locking the max NPC to 10, with a RELEASE version of the game that seems playable. --- Posto-Stuff-ReadmePLZ.txt | 52 ++++- code/base/jk2config.cfg | 469 +++++++++++++++++++------------------- code/game/NPC_spawn.cpp | 220 ++++++++++++++++-- code/game/q_shared.h | 4 +- 4 files changed, 487 insertions(+), 258 deletions(-) diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index af426794..45ae0b4d 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -3,17 +3,67 @@ Findings on this Randomizer : - Some NPC have to be locked, otherwise, we might get undefined behavior in cutscene or else. - In ns_streets, no matter which npc (except the ones in the little arena) are forced on a path. - IMPOSSIBLE to start a new game. +- NPC Spawn are determined at the start of the map, not when you hit triggers. If so, then why does it lag ? (Other are lagging, I'm not). TODO : - Lock all necessarry NPC per map (right now thinking about undercity and assembly, to open doors). - Fixing G_FindConfigstringIndex (very hard). - Stop the crashes (very hard). - Maybe add some kind of items randomize ? Except the necessarry ones ofc. +- Some NPC don't spawn, maybe it's an entity not finished like monster_fish. Need to lock them out. + +List of non-working NPC : +- monster_flier2 +- monster_fish +- claw +- lizard +- swamp +- murjj Crash : common.cpp, line 296 It happens because of G_FindConfigstringIndex each time it seems. I don't know how to fix that, because if it's truly this case every time, it could be a cool mod :/ q_shared : upped the max sounds and models. +I mean, it works, but limiting the number of different kind of NPC is the better idea. For items : -classname : item_bacta, origin : X,Y,Z \ No newline at end of file +classname : item_bacta, origin : X,Y,Z + +G_CreateG2AttachedWeaponModel : assert at line 249 crashes +You can't give yourself a lightsaber before trial ???? +It makes the game crash for some reason +In trial : models/wepaons2/saber/saber_w.glm +In kejim_base : NULL, unable to read memory +In ns_street : models/weapons2/saber/saber_w.glm, so the same as in trial +g_utils.cpp line 1001 eventParm < 256 +noweap.md3 ????????? + +Idea : Lock it to 10 MAX, so that 1=Kyle, 2=NeededNPC, 3=NeededNPC, 4=maybe needednpc or a random one, 5+ = the rest +Here is what I could grab as the max number of different NPC on a map in Vanilla (thinking about big map) : +- Artus_detention : Stormtrooper,Imperial,DroidGonk,Prisoner,MineMonster,R5D2,Kyle,Droid_Sentry, a total of 8, Kyle included +- Bespin_undercity : Kyle,Ugnaught,Rodian,R5D2,Gran,Weequay,Reborn, a total of 7, Kyle included (less than I expected + + +Needed NPC per map : +- None (but need confirmation): kejim_post, kejim_base, artus_mine, yavin_trial, cairn_bay, cairn_reactor, doom_comm, doom_shield, yavin_swamp, yavin_canyon, +- artus_detention : the officer with the loooong sequence +- artus_topside : the prisoners, Desann spawn naturally +- valley : maybe ????? +- yavin_temple : maybe Luke or C3P0 ????? need to confirm +- ns_street : Bartender, but it's already forced. Also the entity that takes away the briar blaster need to be 'humanoid' or the game will crash, need to check that. +- ns_hideout : Lando and Reelo, but both are already forced +- ns_starpas : Lando and maybe Reelo +- bespin_undercity : the guy who opens the door, and R5D2 are forced (need to confirm) +- bespin_streets : R5D2 already forced +- bespin_platform : Tavion is forced +- cairn_assembly : The officer that open the door, maybe something else +- cairn_dock1 : maybe forcing everything here, because random NPC behavior are strange, also Luke and Desann +- doom_detention : the officer that open the door and Jan +- yavin_courtyard : maybe locking everything here (the trooper shoioting the rebel, the jedis are maybe necessary to unlock the scene) + + +CURRENT SITUATION : I locked the number of max unique NPC to 10 for now. +In DEBUG, the game is way less permissing and throw errors often. +But in RELEASE ? It seems plyable, I will do a full playthrought to confirm that. + + diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index 303b48f1..6239ff32 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -19,7 +19,6 @@ bind - "weapon 0" bind . "+moveright" bind / "+mlook" bind 0 "weapon 10" -bind 1 "weapon 1" bind 2 "weapon 2" bind 3 "weapon 3" bind 4 "weapon 4" @@ -69,238 +68,238 @@ bind MOUSE5 "force_throw" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta r_weatherScale "1" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta d_slowmodeath "0" -seta ui_iscensored "0" -seta g_speedFactorLanding "1.0" -seta g_saber_color "yellow" -seta g_saberAutoAim "1" -seta g_saberAnimSpeed "1" -seta g_saberMoveSpeed "1" -seta g_saberRealisticCombat "0" -seta g_saberAutoBlocking "1" -seta g_dismemberProbabilities "1" -seta g_dismemberment "3" -seta cg_strafeHelperColorSpeedA "0.9" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperCenter "1" -seta cg_drawStrafeHelper "0" -seta cg_speedColorA "0.9" -seta cg_speedColorB "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorR "1.0" -seta cg_speedY "75" -seta cg_speedX "0" -seta cg_speedScale "0.9" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperY "0" -seta cg_jumpHelperX "0" -seta cg_drawJumpHelper "0" -seta cg_drawOverbounceInfo "0" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSecrets "0" -seta cg_reliableAnimSounds "1" -seta cg_missionInfoCentered "1" -seta cg_bobroll "0.002" -seta cg_bobpitch "0.002" -seta cg_bobup "0.005" -seta cg_runroll "0.005" -seta cg_runpitch "0.002" -seta cg_simpleItems "0" -seta cg_crosshairY "0" -seta cg_crosshairX "0" -seta cg_crosshairSize "24" -seta cg_crosshairIdentifyTarget "1" -seta cg_dynamicCrosshair "1" -seta cg_drawAmmoWarning "1" -seta cg_drawSnapshot "0" -seta cg_drawServerFPS "1" -seta cg_drawFPS "1" -seta cg_drawTimer "1" -seta cg_drawStatus "1" -seta cg_draw2D "1" -seta cg_stereoSeparation "0.4" -seta cg_drawGun "1" -seta cm_playerCurveClip "1" -seta cg_crosshairForceHint "1" -seta g_spskill "0" -seta cg_drawSpeed "0" -seta cg_gunAutoFirst "1" -seta cg_saberAutoThird "0" -seta g_subtitles "2" -seta ui_r_glCustom "4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_bigFont "0.4" -seta ui_smallFont "0.25" -seta ui_menuFiles "ui/menus.txt" -seta cg_marks "1" -seta cg_drawCrosshair "1" -seta ff_delay "40" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta use_ff "1" -seta s_soundpoolmegs "25" -seta s_UseOpenAL "0" -seta s_mp3overhead "31756" -seta s_language "francais" -seta s_mixPreStep "0.05" -seta s_mixahead "0.2" -seta s_allowDynamicMusic "1" -seta s_khz "22" -seta s_separation "0.5" -seta s_musicvolume "0.023438" -seta s_volumeVoice "0.062500" -seta s_volume "0.054688" -seta vid_ypos "0" -seta vid_xpos "0" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta r_modelpoolmegs "20" -seta cg_shadows "0" -seta r_showtriscolor "0" -seta r_primitives "0" -seta r_facePlaneCull "1" -seta r_gamma "1.359375" -seta r_swapInterval "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_finish "0" -seta r_dlightBacks "1" -seta r_dynamiclight "1" -seta r_drawSun "0" -seta r_fastsky "0" -seta r_ignoreGLErrors "1" -seta r_lodscale "10" -seta r_flares "1" -seta r_lodbias "0" -seta r_lodCurveError "250" -seta r_intensity "1" -seta r_ignoreFastPath "1" -seta r_subdivisions "4" -seta r_vertexLight "0" -seta r_simpleMipMaps "1" -seta r_customaspect "1" -seta r_customheight "1024" -seta r_customwidth "1600" -seta r_fullscreen "0" -seta r_mode "8" -seta r_ignorehwgamma "0" -seta r_overBrightBits "1" -seta r_depthbits "24" -seta r_stencilbits "8" -seta r_stereo "0" -seta r_colorbits "32" -seta r_texturebitslm "0" -seta r_texturebits "0" -seta r_detailtextures "1" -seta r_picmip "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_ext_texture_env_add "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_multitexture "1" -seta r_ext_gamma_control "1" -seta r_ext_preferred_tc_method "0" -seta r_ext_compress_lightmaps "0" -seta r_ext_compress_textures "1" -seta r_allowExtensions "1" -seta handicap "100" -seta sex "male" -seta snaps "20" -seta name "Kyle" -seta m_filter "0" -seta m_side "0.25" -seta m_forward "0.25" -seta m_yaw "0.022" -seta m_pitch "0.022" -seta cg_autoswitch "0" -seta cl_VideoQuality "0" -seta cl_ingameVideo "1" -seta cl_freelook "1" -seta cl_mouseAccel "0" -seta sensitivity "5" -seta cl_run "1" -seta cl_packetdup "1" -seta cl_maxpackets "30" -seta cl_anglespeedkey "1.5" -seta cl_pitchspeed "140" -seta cl_yawspeed "140" -seta panoNumShots "10" -seta conAlpha "1.6" -seta sv_timedCheckpointMaxZ "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinX "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeIL "0" -seta joy_ybutton "0" -seta joy_xbutton "1" -seta js_ffmult "3.0" -seta joy_threshold "0.15" -seta in_joyBallScale "0.02" -seta in_joystick "0" -seta in_mouse_raw "1" -seta in_mouse "-1" -seta in_mididevice "0" -seta in_midichannel "1" -seta in_midiport "1" -seta in_midi "0" -seta sp_language "1" seta com_maxfps "125" +seta sp_language "1" +seta in_midi "0" +seta in_midiport "1" +seta in_midichannel "1" +seta in_mididevice "0" +seta in_mouse "-1" +seta in_mouse_raw "1" +seta in_joystick "0" +seta in_joyBallScale "0.02" +seta joy_threshold "0.15" +seta js_ffmult "3.0" +seta joy_xbutton "1" +seta joy_ybutton "0" +seta sv_speedrunModeIL "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_timedCheckpointMinX "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxZ "0" +seta conAlpha "1.6" +seta panoNumShots "10" +seta cl_yawspeed "140" +seta cl_pitchspeed "140" +seta cl_anglespeedkey "1.5" +seta cl_maxpackets "30" +seta cl_packetdup "1" +seta cl_run "1" +seta sensitivity "5" +seta cl_mouseAccel "0" +seta cl_freelook "1" +seta cl_ingameVideo "1" +seta cl_VideoQuality "0" +seta cg_autoswitch "0" +seta m_pitch "0.022" +seta m_yaw "0.022" +seta m_forward "0.25" +seta m_side "0.25" +seta m_filter "0" +seta name "Kyle" +seta snaps "20" +seta sex "male" +seta handicap "100" +seta r_allowExtensions "1" +seta r_ext_compress_textures "1" +seta r_ext_compress_lightmaps "0" +seta r_ext_preferred_tc_method "0" +seta r_ext_gamma_control "1" +seta r_ext_multitexture "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_texture_env_add "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_picmip "1" +seta r_detailtextures "1" +seta r_texturebits "0" +seta r_texturebitslm "0" +seta r_colorbits "32" +seta r_stereo "0" +seta r_stencilbits "8" +seta r_depthbits "24" +seta r_overBrightBits "1" +seta r_ignorehwgamma "0" +seta r_mode "8" +seta r_fullscreen "0" +seta r_customwidth "1600" +seta r_customheight "1024" +seta r_customaspect "1" +seta r_simpleMipMaps "1" +seta r_vertexLight "0" +seta r_subdivisions "4" +seta r_ignoreFastPath "1" +seta r_intensity "1" +seta r_lodCurveError "250" +seta r_lodbias "0" +seta r_flares "1" +seta r_lodscale "10" +seta r_ignoreGLErrors "1" +seta r_fastsky "0" +seta r_drawSun "0" +seta r_dynamiclight "1" +seta r_dlightBacks "1" +seta r_finish "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_swapInterval "0" +seta r_gamma "1.359375" +seta r_facePlaneCull "1" +seta r_primitives "0" +seta r_showtriscolor "0" +seta cg_shadows "0" +seta r_modelpoolmegs "20" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta vid_xpos "0" +seta vid_ypos "0" +seta s_volume "0.039062" +seta s_volumeVoice "0.039062" +seta s_musicvolume "0.015625" +seta s_separation "0.5" +seta s_khz "22" +seta s_allowDynamicMusic "1" +seta s_mixahead "0.2" +seta s_mixPreStep "0.05" +seta s_language "francais" +seta s_mp3overhead "31756" +seta s_UseOpenAL "0" +seta s_soundpoolmegs "25" +seta use_ff "1" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta ff_delay "40" +seta cg_drawCrosshair "1" +seta cg_marks "1" +seta ui_menuFiles "ui/menus.txt" +seta ui_smallFont "0.25" +seta ui_bigFont "0.4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_r_glCustom "4" +seta g_subtitles "2" +seta cg_saberAutoThird "0" +seta cg_gunAutoFirst "1" +seta cg_drawSpeed "0" +seta g_spskill "0" +seta cg_crosshairForceHint "1" +seta cm_playerCurveClip "1" +seta cg_drawGun "1" +seta cg_stereoSeparation "0.4" +seta cg_draw2D "1" +seta cg_drawStatus "1" +seta cg_drawTimer "1" +seta cg_drawFPS "1" +seta cg_drawServerFPS "1" +seta cg_drawSnapshot "0" +seta cg_drawAmmoWarning "1" +seta cg_dynamicCrosshair "1" +seta cg_crosshairIdentifyTarget "1" +seta cg_crosshairSize "24" +seta cg_crosshairX "0" +seta cg_crosshairY "0" +seta cg_simpleItems "0" +seta cg_runpitch "0.002" +seta cg_runroll "0.005" +seta cg_bobup "0.005" +seta cg_bobpitch "0.002" +seta cg_bobroll "0.002" +seta cg_missionInfoCentered "1" +seta cg_reliableAnimSounds "1" +seta cg_drawSecrets "0" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawOverbounceInfo "0" +seta cg_drawJumpHelper "0" +seta cg_jumpHelperX "0" +seta cg_jumpHelperY "0" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_speedScale "0.9" +seta cg_speedX "0" +seta cg_speedY "75" +seta cg_speedColorR "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorB "1.0" +seta cg_speedColorA "0.9" +seta cg_drawStrafeHelper "0" +seta cg_strafeHelperCenter "1" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedA "0.9" +seta g_dismemberment "3" +seta g_dismemberProbabilities "1" +seta g_saberAutoBlocking "1" +seta g_saberRealisticCombat "0" +seta g_saberMoveSpeed "1" +seta g_saberAnimSpeed "1" +seta g_saberAutoAim "1" +seta g_saber_color "yellow" +seta g_speedFactorLanding "1.0" +seta ui_iscensored "0" +seta d_slowmodeath "0" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta r_weatherScale "1" diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 98e0a74a..778cf0d2 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2783,377 +2783,555 @@ void SP_NPC_Droid_Protocol( gentity_t *self) NPC_Protocol_Precache(); } + // The Posto is for faster search so I know what I edited +const int tabSize = 10; +short tabLockedInNPC[tabSize] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +short currentTabPosition = 0; +char lastKnownMap[32] = "first_iteration"; + +void MapChanged() +{ + //strcpy(lastKnownMap, level.mapname); + //lastKnownMap = level.mapname; + for (int i = 0; i < tabSize; i++) + { + tabLockedInNPC[i] = -1; + } + currentTabPosition = 0; + // We might have to lock Kyle, we will see what happen. + // tabLockedInNPC[0] = 0; + // currentTabPosition = 1; +} +void CheckIfMapChanged() +{ + // Strange things are occuring, lastKnownMap is getting his 4 first byte are getting overwritten, but I don't know why or how. + if (strcmp(lastKnownMap, level.mapname) != 0) + { + strcpy(lastKnownMap, level.mapname); + MapChanged(); + } +} +bool IsRNGInTab(int source) +{ + for (int i = 0; i < tabSize; i++) + { + if (tabLockedInNPC[i] == source) return 1; + } + return 0; +} +bool IsThereDuplicateInTab(int source) +{ + for (int i = 0; i < tabSize; i++) + { + if (tabLockedInNPC[i] == source) return 1; + } + return 0; +} +void PopulateNPCTab(int source) +{ + if (!IsThereDuplicateInTab(source)) // Safe measure to not corrupt lastKnownMap + { + tabLockedInNPC[currentTabPosition] = source; + currentTabPosition++; + } +} + void SP_NPC_Spawn_Random(gentity_t* self) { - // Pas besoin de srand puisqu'il ets call déjà sur g_main.cpp (???????) + // Pas besoin de srand puisqu'il est call déjà sur g_main.cpp (???????) // Modulo de 49 car il y a 49 entités si j'ai bien compté. +1 pour skip Kyle, même si avoir 2 Kyle n'est potentiellement pas un problème. - int who = rand() % 50 ; - switch (who) + int rng = rand() % 50 ; + // Idée d'Amber : limiter le nombre de NPc plutôt que de modifier d'autres valeurs in game qui peuvent potentiellement faire crash le jeu. + // Du coup, tableau de 10 emplacements déclaré plus haut afin de faire mes tests. + + //string messageToWrite = "Random NPC Spawn, number generated is : "+std::to_string(rng)+"\n"; + //gi.Printf(S_COLOR_YELLOW,messageToWrite.c_str()); // We can't catch that, too much logging between that and the moment we have access to the console. + + // Wait, in my video, there were CLEARLY more than 10 kind of NPCs, what did I do wrong ? Ok fixed (if I don't suck) + // Edit : check line 2808 + + // Case : We have a duplicate in our locking NPC array, and we want to have different NPCs + while (IsThereDuplicateInTab(rng) && currentTabPosition!=tabSize) + { + rng = rand() % 50; + } + // Case : We already have 10 NPC loaded, so we want to roll one of them. This can take time, but only during a map load. + while ((currentTabPosition == tabSize && !IsRNGInTab(rng))) + { + rng = rand() % 50; + } + + switch (rng) { case 0: SP_NPC_Kyle(self); + PopulateNPCTab(rng); break; case 1: SP_NPC_Lando(self); + PopulateNPCTab(rng); break; case 2: SP_NPC_Jan(self); + PopulateNPCTab(rng); break; case 3: SP_NPC_Luke(self); + PopulateNPCTab(rng); break; case 4: // Elle a une IA au moins ? SP_NPC_MonMothma(self); + PopulateNPCTab(rng); break; case 5: SP_NPC_Tavion(self); + PopulateNPCTab(rng); break; case 6: // Il a une IA au moins ? SP_NPC_Reelo(self); + PopulateNPCTab(rng); break; case 7: SP_NPC_Galak(self); + PopulateNPCTab(rng); break; case 8: SP_NPC_Desann(self); + PopulateNPCTab(rng); break; case 9: // Il a une IA au moins ? SP_NPC_Bartender(self); + PopulateNPCTab(rng); break; case 10: SP_NPC_MorganKatarn(self); + PopulateNPCTab(rng); break; case 11: SP_NPC_Jedi(self); + PopulateNPCTab(rng); break; case 12: SP_NPC_Prisoner(self); + PopulateNPCTab(rng); break; case 13: SP_NPC_Rebel(self); + PopulateNPCTab(rng); break; case 14: // Le classique SP_NPC_Stormtrooper(self); + PopulateNPCTab(rng); break; case 15: SP_NPC_StormtrooperOfficer(self); + PopulateNPCTab(rng); break; case 16: SP_NPC_Tie_Pilot(self); + PopulateNPCTab(rng); break; case 17: // C'est qui ? SP_NPC_Ugnaught(self); + PopulateNPCTab(rng); break; case 18: // C'est qui ? SP_NPC_Gran(self); + PopulateNPCTab(rng); break; case 19: SP_NPC_Rodian(self); + PopulateNPCTab(rng); break; case 20: SP_NPC_Weequay(self); + PopulateNPCTab(rng); break; case 21: SP_NPC_Trandoshan(self); + PopulateNPCTab(rng); break; case 22: SP_NPC_SwampTrooper(self); + PopulateNPCTab(rng); break; case 23: SP_NPC_Imperial(self); + PopulateNPCTab(rng); break; case 24: SP_NPC_ImpWorker(self); + PopulateNPCTab(rng); break; case 25: SP_NPC_BespinCop(self); + PopulateNPCTab(rng); break; case 26: SP_NPC_Reborn(self); + PopulateNPCTab(rng); break; case 27: SP_NPC_ShadowTrooper(self); + PopulateNPCTab(rng); break; - case 28: // Attention - SP_NPC_Monster_Murjj(self); + case 28: // This entity doesn't work, retry + //SP_NPC_Monster_Murjj(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 29: // Attention - SP_NPC_Monster_Swamp(self); + case 29: // This entity doesn't work, retry + //SP_NPC_Monster_Swamp(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 30: // Attention - SP_NPC_Monster_Howler(self); + case 30: // This entity doesn't work, retry + //SP_NPC_Monster_Howler(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; case 31: SP_NPC_MineMonster(self); + PopulateNPCTab(rng); break; - case 32: // Attention - SP_NPC_Monster_Claw(self); + case 32: // This entity doesn't work, retry + //SP_NPC_Monster_Claw(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 33: // Attention - SP_NPC_Monster_Glider(self); + case 33: // This entity doesn't work, retry + //SP_NPC_Monster_Glider(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 34: // Attention - SP_NPC_Monster_Flier2(self); + case 34: // This entity doesn't work, retry + //SP_NPC_Monster_Flier2(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 35: // Attention - SP_NPC_Monster_Lizard(self); + case 35: // This entity doesn't work, retry + //SP_NPC_Monster_Lizard(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; - case 36: // Attention - SP_NPC_Monster_Fish(self); + case 36: // This entity doesn't work, retry + //SP_NPC_Monster_Fish(self); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; case 37: SP_NPC_Droid_Interrogator(self); + PopulateNPCTab(rng); break; case 38: SP_NPC_Droid_Probe(self); + PopulateNPCTab(rng); break; case 39: SP_NPC_Droid_Mark1(self); + PopulateNPCTab(rng); break; case 40: SP_NPC_Droid_Mark2(self); + PopulateNPCTab(rng); break; case 41: // Attention SP_NPC_Droid_ATST(self); + PopulateNPCTab(rng); //SP_NPC_Stormtrooper(self); break; case 42: SP_NPC_Droid_Seeker(self); + PopulateNPCTab(rng); break; case 43: SP_NPC_Droid_Remote(self); + PopulateNPCTab(rng); break; case 44: SP_NPC_Droid_Sentry(self); + PopulateNPCTab(rng); break; case 45: SP_NPC_Droid_Gonk(self); + PopulateNPCTab(rng); break; case 46: SP_NPC_Droid_Mouse(self); + PopulateNPCTab(rng); break; case 47: SP_NPC_Droid_R2D2(self); + PopulateNPCTab(rng); break; case 48: SP_NPC_Droid_R5D2(self); + PopulateNPCTab(rng); break; case 49: SP_NPC_Droid_Protocol(self); + PopulateNPCTab(rng); break; default: // Secours - SP_NPC_Stormtrooper(self); + //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; } } void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle { - string mapname = level.mapname; // It works, just need to do a list of NPC to lock and everything + CheckIfMapChanged(); SP_NPC_Kyle(self); } void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando { + CheckIfMapChanged(); SP_NPC_Lando(self); } void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan { + CheckIfMapChanged(); + //if (lastKnownMap == "kejim_post") // That's not C + if (strcmp(lastKnownMap,"kejim_post") == 0 ) + { + int proofOfConcept = 777; + } SP_NPC_Jan(self); } void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke { + CheckIfMapChanged(); SP_NPC_Luke(self); } void SP_NPC_MonMothma_Random(gentity_t* self) // MonMothma should always spawn as MonMothma { + CheckIfMapChanged(); SP_NPC_MonMothma(self); } void SP_NPC_Tavion_Random(gentity_t* self) // Tavion should always spawn as Tavion { + CheckIfMapChanged(); SP_NPC_Tavion(self); } void SP_NPC_Reelo_Random(gentity_t* self) // Reelo should always spawn as Reelo { + CheckIfMapChanged(); SP_NPC_Reelo(self); } void SP_NPC_Galak_Random(gentity_t* self) // Galak should always spawn as Galak { + CheckIfMapChanged(); SP_NPC_Galak(self); } void SP_NPC_Desann_Random(gentity_t* self) // Desann should always spawn as Desann { + CheckIfMapChanged(); SP_NPC_Desann(self); } void SP_NPC_Bartender_Random(gentity_t* self) // Bartender should always spawn as Bartender { + CheckIfMapChanged(); SP_NPC_Bartender(self); } void SP_NPC_MorganKatarn_Random(gentity_t* self) // Morgarn should always spawn as Morgarn { + CheckIfMapChanged(); SP_NPC_MorganKatarn(self); } void SP_NPC_Jedi_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Prisoner_Random(gentity_t* self) // Prisoners should spawn as themselves { + CheckIfMapChanged(); SP_NPC_Prisoner(self); } void SP_NPC_Rebel_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Stormtrooper_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_StormtrooperOfficer_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Tie_Pilot_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaught { + CheckIfMapChanged(); SP_NPC_Ugnaught(self); } void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Rodian_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Weequay_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Trandoshan_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_SwampTrooper_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Imperial_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_ImpWorker_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_BespinCop_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Reborn_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_ShadowTrooper_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Murjj_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Swamp_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Howler_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Claw_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Glider_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Flier2_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Lizard_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Fish_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_MineMonster_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Interrogator_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Probe_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Mark1_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Mark2_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_ATST_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Seeker_Random(gentity_t* self) // Seekers should always be seekers, at least in speedruns { + CheckIfMapChanged(); SP_NPC_Droid_Seeker(self); } void SP_NPC_Droid_Remote_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Sentry_Random(gentity_t* self) // Who is that ? { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Gonk_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse { + CheckIfMapChanged(); SP_NPC_Droid_Mouse(self); } void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self { + CheckIfMapChanged(); SP_NPC_Droid_R2D2(self); } void SP_NPC_Droid_R5D2_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Droid_R5D2(self); } void SP_NPC_Droid_Protocol_Random(gentity_t* self) { + CheckIfMapChanged(); SP_NPC_Droid_Protocol(self); } diff --git a/code/game/q_shared.h b/code/game/q_shared.h index d476738a..dd077c79 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1156,6 +1156,7 @@ typedef struct { #define MAX_LOCATIONS 64 #define GENTITYNUM_BITS 10 // don't need to send any more +//#define GENTITYNUM_BITS 11 // Posto : ok never touch this, or the game explode #define MAX_GENTITIES (1< MAX_CONFIGSTRINGS #endif -#define MAX_GAMESTATE_CHARS 16000 +//#define MAX_GAMESTATE_CHARS 16000 +#define MAX_GAMESTATE_CHARS 32000 // Posto : might need to increase that typedef struct { int stringOffsets[MAX_CONFIGSTRINGS]; char stringData[MAX_GAMESTATE_CHARS]; From ef9a576c2fbe253bd3ea88b2aa8e6c5d8220e18f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Sat, 5 Oct 2024 00:05:55 +0200 Subject: [PATCH 05/62] Added a way to access a funciton in NPC_spawn.cpp via the command "randomizerdebug" --- code/base/jk2config.cfg | 471 ++++++++++++++++++++-------------------- code/cgame/cg_main.cpp | 2 + code/game/NPC_spawn.cpp | 8 +- code/game/g_cmds.cpp | 10 +- code/game/g_svcmds.cpp | 10 + 5 files changed, 260 insertions(+), 241 deletions(-) diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index 6239ff32..4c87a6b6 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -19,6 +19,7 @@ bind - "weapon 0" bind . "+moveright" bind / "+mlook" bind 0 "weapon 10" +bind 1 "weapon 1" bind 2 "weapon 2" bind 3 "weapon 3" bind 4 "weapon 4" @@ -64,242 +65,242 @@ bind F11 "uimenu ingamesavemenu" bind END "centerview" bind PGDN "+lookdown" bind MOUSE3 "zoom" -bind MOUSE5 "force_throw" +bind MOUSE5 "+force_lightning" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta com_maxfps "125" -seta sp_language "1" -seta in_midi "0" -seta in_midiport "1" -seta in_midichannel "1" -seta in_mididevice "0" -seta in_mouse "-1" -seta in_mouse_raw "1" -seta in_joystick "0" -seta in_joyBallScale "0.02" -seta joy_threshold "0.15" -seta js_ffmult "3.0" -seta joy_xbutton "1" -seta joy_ybutton "0" -seta sv_speedrunModeIL "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_timedCheckpointMinX "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxZ "0" -seta conAlpha "1.6" -seta panoNumShots "10" -seta cl_yawspeed "140" -seta cl_pitchspeed "140" -seta cl_anglespeedkey "1.5" -seta cl_maxpackets "30" -seta cl_packetdup "1" -seta cl_run "1" -seta sensitivity "5" -seta cl_mouseAccel "0" -seta cl_freelook "1" -seta cl_ingameVideo "1" -seta cl_VideoQuality "0" -seta cg_autoswitch "0" -seta m_pitch "0.022" -seta m_yaw "0.022" -seta m_forward "0.25" -seta m_side "0.25" -seta m_filter "0" -seta name "Kyle" -seta snaps "20" -seta sex "male" -seta handicap "100" -seta r_allowExtensions "1" -seta r_ext_compress_textures "1" -seta r_ext_compress_lightmaps "0" -seta r_ext_preferred_tc_method "0" -seta r_ext_gamma_control "1" -seta r_ext_multitexture "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_texture_env_add "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_picmip "1" -seta r_detailtextures "1" -seta r_texturebits "0" -seta r_texturebitslm "0" -seta r_colorbits "32" -seta r_stereo "0" -seta r_stencilbits "8" -seta r_depthbits "24" -seta r_overBrightBits "1" -seta r_ignorehwgamma "0" -seta r_mode "8" -seta r_fullscreen "0" -seta r_customwidth "1600" -seta r_customheight "1024" -seta r_customaspect "1" -seta r_simpleMipMaps "1" -seta r_vertexLight "0" -seta r_subdivisions "4" -seta r_ignoreFastPath "1" -seta r_intensity "1" -seta r_lodCurveError "250" -seta r_lodbias "0" -seta r_flares "1" -seta r_lodscale "10" -seta r_ignoreGLErrors "1" -seta r_fastsky "0" -seta r_drawSun "0" -seta r_dynamiclight "1" -seta r_dlightBacks "1" -seta r_finish "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_swapInterval "0" -seta r_gamma "1.359375" -seta r_facePlaneCull "1" -seta r_primitives "0" -seta r_showtriscolor "0" -seta cg_shadows "0" -seta r_modelpoolmegs "20" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta vid_xpos "0" -seta vid_ypos "0" -seta s_volume "0.039062" -seta s_volumeVoice "0.039062" -seta s_musicvolume "0.015625" -seta s_separation "0.5" -seta s_khz "22" -seta s_allowDynamicMusic "1" -seta s_mixahead "0.2" -seta s_mixPreStep "0.05" -seta s_language "francais" -seta s_mp3overhead "31756" -seta s_UseOpenAL "0" -seta s_soundpoolmegs "25" -seta use_ff "1" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta ff_delay "40" -seta cg_drawCrosshair "1" -seta cg_marks "1" -seta ui_menuFiles "ui/menus.txt" -seta ui_smallFont "0.25" -seta ui_bigFont "0.4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_r_glCustom "4" -seta g_subtitles "2" -seta cg_saberAutoThird "0" -seta cg_gunAutoFirst "1" -seta cg_drawSpeed "0" -seta g_spskill "0" -seta cg_crosshairForceHint "1" -seta cm_playerCurveClip "1" -seta cg_drawGun "1" -seta cg_stereoSeparation "0.4" -seta cg_draw2D "1" -seta cg_drawStatus "1" -seta cg_drawTimer "1" -seta cg_drawFPS "1" -seta cg_drawServerFPS "1" -seta cg_drawSnapshot "0" -seta cg_drawAmmoWarning "1" -seta cg_dynamicCrosshair "1" -seta cg_crosshairIdentifyTarget "1" -seta cg_crosshairSize "24" -seta cg_crosshairX "0" -seta cg_crosshairY "0" -seta cg_simpleItems "0" -seta cg_runpitch "0.002" -seta cg_runroll "0.005" -seta cg_bobup "0.005" -seta cg_bobpitch "0.002" -seta cg_bobroll "0.002" -seta cg_missionInfoCentered "1" -seta cg_reliableAnimSounds "1" -seta cg_drawSecrets "0" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawOverbounceInfo "0" -seta cg_drawJumpHelper "0" -seta cg_jumpHelperX "0" -seta cg_jumpHelperY "0" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_speedScale "0.9" -seta cg_speedX "0" -seta cg_speedY "75" -seta cg_speedColorR "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorB "1.0" -seta cg_speedColorA "0.9" -seta cg_drawStrafeHelper "0" -seta cg_strafeHelperCenter "1" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedA "0.9" -seta g_dismemberment "3" -seta g_dismemberProbabilities "1" -seta g_saberAutoBlocking "1" -seta g_saberRealisticCombat "0" -seta g_saberMoveSpeed "1" -seta g_saberAnimSpeed "1" -seta g_saberAutoAim "1" -seta g_saber_color "yellow" -seta g_speedFactorLanding "1.0" -seta ui_iscensored "0" -seta d_slowmodeath "0" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" seta r_weatherScale "1" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta d_slowmodeath "0" +seta ui_iscensored "0" +seta g_speedFactorLanding "1.0" +seta g_saber_color "yellow" +seta g_saberAutoAim "1" +seta g_saberAnimSpeed "1" +seta g_saberMoveSpeed "1" +seta g_saberRealisticCombat "0" +seta g_saberAutoBlocking "1" +seta g_dismemberProbabilities "1" +seta g_dismemberment "3" +seta cg_strafeHelperColorSpeedA "0.9" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperCenter "1" +seta cg_drawStrafeHelper "0" +seta cg_speedColorA "0.9" +seta cg_speedColorB "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorR "1.0" +seta cg_speedY "75" +seta cg_speedX "0" +seta cg_speedScale "0.9" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperY "0" +seta cg_jumpHelperX "0" +seta cg_drawJumpHelper "0" +seta cg_drawOverbounceInfo "0" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSecrets "0" +seta cg_reliableAnimSounds "1" +seta cg_missionInfoCentered "1" +seta cg_bobroll "0.002" +seta cg_bobpitch "0.002" +seta cg_bobup "0.005" +seta cg_runroll "0.005" +seta cg_runpitch "0.002" +seta cg_simpleItems "0" +seta cg_crosshairY "0" +seta cg_crosshairX "0" +seta cg_crosshairSize "24" +seta cg_crosshairIdentifyTarget "1" +seta cg_dynamicCrosshair "1" +seta cg_drawAmmoWarning "1" +seta cg_drawSnapshot "0" +seta cg_drawServerFPS "1" +seta cg_drawFPS "1" +seta cg_drawTimer "1" +seta cg_drawStatus "1" +seta cg_draw2D "1" +seta cg_stereoSeparation "0.4" +seta cg_drawGun "1" +seta cm_playerCurveClip "1" +seta cg_crosshairForceHint "1" +seta g_spskill "0" +seta cg_drawSpeed "0" +seta cg_gunAutoFirst "1" +seta cg_saberAutoThird "0" +seta g_subtitles "2" +seta ui_r_glCustom "4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_bigFont "0.4" +seta ui_smallFont "0.25" +seta ui_menuFiles "ui/menus.txt" +seta cg_marks "1" +seta cg_drawCrosshair "1" +seta ff_delay "40" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta use_ff "1" +seta s_soundpoolmegs "25" +seta s_UseOpenAL "0" +seta s_mp3overhead "31756" +seta s_language "francais" +seta s_mixPreStep "0.05" +seta s_mixahead "0.2" +seta s_allowDynamicMusic "1" +seta s_khz "22" +seta s_separation "0.5" +seta s_musicvolume "0.015625" +seta s_volumeVoice "0.039062" +seta s_volume "0.039062" +seta vid_ypos "0" +seta vid_xpos "0" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta r_modelpoolmegs "20" +seta cg_shadows "0" +seta r_showtriscolor "0" +seta r_primitives "0" +seta r_facePlaneCull "1" +seta r_gamma "1.359375" +seta r_swapInterval "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_finish "0" +seta r_dlightBacks "1" +seta r_dynamiclight "1" +seta r_drawSun "0" +seta r_fastsky "0" +seta r_ignoreGLErrors "1" +seta r_lodscale "10" +seta r_flares "1" +seta r_lodbias "0" +seta r_lodCurveError "250" +seta r_intensity "1" +seta r_ignoreFastPath "1" +seta r_subdivisions "4" +seta r_vertexLight "0" +seta r_simpleMipMaps "1" +seta r_customaspect "1" +seta r_customheight "1024" +seta r_customwidth "1600" +seta r_fullscreen "0" +seta r_mode "8" +seta r_ignorehwgamma "0" +seta r_overBrightBits "1" +seta r_depthbits "24" +seta r_stencilbits "8" +seta r_stereo "0" +seta r_colorbits "32" +seta r_texturebitslm "0" +seta r_texturebits "0" +seta r_detailtextures "1" +seta r_picmip "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_ext_texture_env_add "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_multitexture "1" +seta r_ext_gamma_control "1" +seta r_ext_preferred_tc_method "0" +seta r_ext_compress_lightmaps "0" +seta r_ext_compress_textures "1" +seta r_allowExtensions "1" +seta handicap "100" +seta sex "male" +seta snaps "20" +seta name "Kyle" +seta m_filter "0" +seta m_side "0.25" +seta m_forward "0.25" +seta m_yaw "0.022" +seta m_pitch "0.022" +seta cg_autoswitch "0" +seta cl_VideoQuality "0" +seta cl_ingameVideo "1" +seta cl_freelook "1" +seta cl_mouseAccel "0" +seta sensitivity "5" +seta cl_run "1" +seta cl_packetdup "1" +seta cl_maxpackets "30" +seta cl_anglespeedkey "1.5" +seta cl_pitchspeed "140" +seta cl_yawspeed "140" +seta panoNumShots "10" +seta conAlpha "1.6" +seta sv_timedCheckpointMaxZ "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinX "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeIL "0" +seta joy_ybutton "0" +seta joy_xbutton "1" +seta js_ffmult "3.0" +seta joy_threshold "0.15" +seta in_joyBallScale "0.02" +seta in_joystick "0" +seta in_mouse_raw "1" +seta in_mouse "-1" +seta in_mididevice "0" +seta in_midichannel "1" +seta in_midiport "1" +seta in_midi "0" +seta sp_language "1" +seta com_maxfps "125" diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 4dcad20f..7df57e1b 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -2034,6 +2034,8 @@ void CG_Init( int serverCommandSequence ) { cgi_AddCommand ("kill"); cgi_AddCommand ("give"); cgi_AddCommand ("god"); + // Posto : we might need that + cgi_AddCommand("randomizerdebug"); cgi_AddCommand ("notarget"); cgi_AddCommand ("noclip"); cgi_AddCommand ("undying"); diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 778cf0d2..b76b153a 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2805,7 +2805,6 @@ void MapChanged() } void CheckIfMapChanged() { - // Strange things are occuring, lastKnownMap is getting his 4 first byte are getting overwritten, but I don't know why or how. if (strcmp(lastKnownMap, level.mapname) != 0) { strcpy(lastKnownMap, level.mapname); @@ -2836,6 +2835,10 @@ void PopulateNPCTab(int source) currentTabPosition++; } } +void RandomizerPrintAll() +{ + gi.Printf(S_COLOR_GREEN"We are getting to this function, we can log things here !\n"); +} void SP_NPC_Spawn_Random(gentity_t* self) { @@ -2848,9 +2851,6 @@ void SP_NPC_Spawn_Random(gentity_t* self) //string messageToWrite = "Random NPC Spawn, number generated is : "+std::to_string(rng)+"\n"; //gi.Printf(S_COLOR_YELLOW,messageToWrite.c_str()); // We can't catch that, too much logging between that and the moment we have access to the console. - // Wait, in my video, there were CLEARLY more than 10 kind of NPCs, what did I do wrong ? Ok fixed (if I don't suck) - // Edit : check line 2808 - // Case : We have a duplicate in our locking NPC array, and we want to have different NPCs while (IsThereDuplicateInTab(rng) && currentTabPosition!=tabSize) { diff --git a/code/game/g_cmds.cpp b/code/game/g_cmds.cpp index e4b4890c..2967eab0 100644 --- a/code/game/g_cmds.cpp +++ b/code/game/g_cmds.cpp @@ -6,6 +6,9 @@ #include "objectives.h" #include "wp_saber.h" +//#include <..\game\NPC_spawn.cpp> +extern void RandomizerPrintAll(); // It's declared in NPC_spawn.cpp + extern bool in_camera; extern void ForceThrow( gentity_t *self, qboolean pull ); @@ -1030,8 +1033,11 @@ void ClientCommand( int clientNum ) { return; } - if (Q_stricmp (cmd, "give") == 0) - Cmd_Give_f (ent); + // Posto : maybe adding a command is here ? + if (Q_stricmp(cmd, "give") == 0) + Cmd_Give_f(ent); + else if (Q_stricmp(cmd, "randomizerdebug") == 0) + RandomizerPrintAll(); else if (Q_stricmp (cmd, "god") == 0) Cmd_God_f (ent); else if (Q_stricmp (cmd, "undying") == 0) diff --git a/code/game/g_svcmds.cpp b/code/game/g_svcmds.cpp index bd0d003c..936786b5 100644 --- a/code/game/g_svcmds.cpp +++ b/code/game/g_svcmds.cpp @@ -7,6 +7,9 @@ #include "g_icarus.h" #include "wp_saber.h" +//#include <..\game\NPC_spawn.cpp> +extern void RandomizerPrintAll(); // It's declared in NPC_spawn.cpp + extern void Q3_SetViewEntity(int entID, const char *name); extern qboolean G_ClearViewEntity( gentity_t *ent ); @@ -923,6 +926,13 @@ qboolean ConsoleCommand( void ) { { Svcmd_ExitView_f(); } + + // Posto : Maybe adding a command is here ? + if (Q_stricmp(cmd, "randomizerdebug") == 0) + { + + RandomizerPrintAll(); + } return qfalse; } From 17da9924fe1c0f40517a830bb2073c6858179a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Sat, 5 Oct 2024 16:49:05 +0200 Subject: [PATCH 06/62] Changin randomizerdebug to randomizer_debug and adding some results to this command. --- Posto-Stuff-ReadmePLZ.txt | 11 +- code/base/jk2config.cfg | 471 +++++++++++++++++++------------------- code/cgame/cg_main.cpp | 4 +- code/game/NPC_spawn.cpp | 177 +++++++++++++- code/game/g_cmds.cpp | 10 +- code/game/g_svcmds.cpp | 13 +- 6 files changed, 433 insertions(+), 253 deletions(-) diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index 45ae0b4d..51871224 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -66,4 +66,13 @@ CURRENT SITUATION : I locked the number of max unique NPC to 10 for now. In DEBUG, the game is way less permissing and throw errors often. But in RELEASE ? It seems plyable, I will do a full playthrought to confirm that. - +I tried to do entire playthought, here is a list of softlock I had (stopped at topside) : +- Two or more NPC spawn location being too close is a problem, if for exemple ATSTs tried to spawn, only one will THEN the other when there is enough space +- kejim_base : the NPC that spawned behind the door could'nt spawn, it was a big droid. Making it impossible for the cutscene to execute +- artus_detention : +NPC will NOT respect that truce when the guard is activated, not really a softlock but careful. Also, any NPC can trigger the guard, not only Kyle. +The guard being too big will not work. +Fortunatly, no matter which team the NPC spawned, it will be overwritten and will always be havin the same path and behavior as the guardian. +- artus_topside : +Didn't manage to load the map under unknown conditions +The path finding of NPC that spawn instead of the stormtrooper seems to always be broken diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index 4c87a6b6..f57e7051 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -5,7 +5,7 @@ bind CTRL "+movedown" bind ALT "force_pull" bind TAB "cg_thirdperson !" bind ENTER "invuse" -bind KP_INS "vstr svfps1" +bind KP_INS "vstr easycheatforrandomizerdebug" bind KP_DOWNARROW "use_seeker" bind KP_LEFTARROW "use_lightamp_goggles" bind KP_5 "use_sentry" @@ -69,238 +69,239 @@ bind MOUSE5 "+force_lightning" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta r_weatherScale "1" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta d_slowmodeath "0" -seta ui_iscensored "0" -seta g_speedFactorLanding "1.0" -seta g_saber_color "yellow" -seta g_saberAutoAim "1" -seta g_saberAnimSpeed "1" -seta g_saberMoveSpeed "1" -seta g_saberRealisticCombat "0" -seta g_saberAutoBlocking "1" -seta g_dismemberProbabilities "1" -seta g_dismemberment "3" -seta cg_strafeHelperColorSpeedA "0.9" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperCenter "1" -seta cg_drawStrafeHelper "0" -seta cg_speedColorA "0.9" -seta cg_speedColorB "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorR "1.0" -seta cg_speedY "75" -seta cg_speedX "0" -seta cg_speedScale "0.9" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperY "0" -seta cg_jumpHelperX "0" -seta cg_drawJumpHelper "0" -seta cg_drawOverbounceInfo "0" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSecrets "0" -seta cg_reliableAnimSounds "1" -seta cg_missionInfoCentered "1" -seta cg_bobroll "0.002" -seta cg_bobpitch "0.002" -seta cg_bobup "0.005" -seta cg_runroll "0.005" -seta cg_runpitch "0.002" -seta cg_simpleItems "0" -seta cg_crosshairY "0" -seta cg_crosshairX "0" -seta cg_crosshairSize "24" -seta cg_crosshairIdentifyTarget "1" -seta cg_dynamicCrosshair "1" -seta cg_drawAmmoWarning "1" -seta cg_drawSnapshot "0" -seta cg_drawServerFPS "1" -seta cg_drawFPS "1" -seta cg_drawTimer "1" -seta cg_drawStatus "1" -seta cg_draw2D "1" -seta cg_stereoSeparation "0.4" -seta cg_drawGun "1" -seta cm_playerCurveClip "1" -seta cg_crosshairForceHint "1" -seta g_spskill "0" -seta cg_drawSpeed "0" -seta cg_gunAutoFirst "1" -seta cg_saberAutoThird "0" -seta g_subtitles "2" -seta ui_r_glCustom "4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_bigFont "0.4" -seta ui_smallFont "0.25" -seta ui_menuFiles "ui/menus.txt" -seta cg_marks "1" -seta cg_drawCrosshair "1" -seta ff_delay "40" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta use_ff "1" -seta s_soundpoolmegs "25" -seta s_UseOpenAL "0" -seta s_mp3overhead "31756" -seta s_language "francais" -seta s_mixPreStep "0.05" -seta s_mixahead "0.2" -seta s_allowDynamicMusic "1" -seta s_khz "22" -seta s_separation "0.5" -seta s_musicvolume "0.015625" -seta s_volumeVoice "0.039062" -seta s_volume "0.039062" -seta vid_ypos "0" -seta vid_xpos "0" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta r_modelpoolmegs "20" -seta cg_shadows "0" -seta r_showtriscolor "0" -seta r_primitives "0" -seta r_facePlaneCull "1" -seta r_gamma "1.359375" -seta r_swapInterval "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_finish "0" -seta r_dlightBacks "1" -seta r_dynamiclight "1" -seta r_drawSun "0" -seta r_fastsky "0" -seta r_ignoreGLErrors "1" -seta r_lodscale "10" -seta r_flares "1" -seta r_lodbias "0" -seta r_lodCurveError "250" -seta r_intensity "1" -seta r_ignoreFastPath "1" -seta r_subdivisions "4" -seta r_vertexLight "0" -seta r_simpleMipMaps "1" -seta r_customaspect "1" -seta r_customheight "1024" -seta r_customwidth "1600" -seta r_fullscreen "0" -seta r_mode "8" -seta r_ignorehwgamma "0" -seta r_overBrightBits "1" -seta r_depthbits "24" -seta r_stencilbits "8" -seta r_stereo "0" -seta r_colorbits "32" -seta r_texturebitslm "0" -seta r_texturebits "0" -seta r_detailtextures "1" -seta r_picmip "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_ext_texture_env_add "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_multitexture "1" -seta r_ext_gamma_control "1" -seta r_ext_preferred_tc_method "0" -seta r_ext_compress_lightmaps "0" -seta r_ext_compress_textures "1" -seta r_allowExtensions "1" -seta handicap "100" -seta sex "male" -seta snaps "20" -seta name "Kyle" -seta m_filter "0" -seta m_side "0.25" -seta m_forward "0.25" -seta m_yaw "0.022" -seta m_pitch "0.022" -seta cg_autoswitch "0" -seta cl_VideoQuality "0" -seta cl_ingameVideo "1" -seta cl_freelook "1" -seta cl_mouseAccel "0" -seta sensitivity "5" -seta cl_run "1" -seta cl_packetdup "1" -seta cl_maxpackets "30" -seta cl_anglespeedkey "1.5" -seta cl_pitchspeed "140" -seta cl_yawspeed "140" -seta panoNumShots "10" -seta conAlpha "1.6" -seta sv_timedCheckpointMaxZ "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinX "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeIL "0" -seta joy_ybutton "0" -seta joy_xbutton "1" -seta js_ffmult "3.0" -seta joy_threshold "0.15" -seta in_joyBallScale "0.02" -seta in_joystick "0" -seta in_mouse_raw "1" -seta in_mouse "-1" -seta in_mididevice "0" -seta in_midichannel "1" -seta in_midiport "1" -seta in_midi "0" -seta sp_language "1" seta com_maxfps "125" +seta sp_language "1" +seta in_midi "0" +seta in_midiport "1" +seta in_midichannel "1" +seta in_mididevice "0" +seta in_mouse "-1" +seta in_mouse_raw "1" +seta in_joystick "0" +seta in_joyBallScale "0.02" +seta joy_threshold "0.15" +seta js_ffmult "3.0" +seta joy_xbutton "1" +seta joy_ybutton "0" +seta sv_speedrunModeIL "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_timedCheckpointMinX "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxZ "0" +seta conAlpha "1.6" +seta panoNumShots "10" +seta cl_yawspeed "140" +seta cl_pitchspeed "140" +seta cl_anglespeedkey "1.5" +seta cl_maxpackets "30" +seta cl_packetdup "1" +seta cl_run "1" +seta sensitivity "5" +seta cl_mouseAccel "0" +seta cl_freelook "1" +seta cl_ingameVideo "1" +seta cl_VideoQuality "0" +seta cg_autoswitch "0" +seta m_pitch "0.022" +seta m_yaw "0.022" +seta m_forward "0.25" +seta m_side "0.25" +seta m_filter "0" +seta name "Kyle" +seta snaps "20" +seta sex "male" +seta handicap "100" +seta r_allowExtensions "1" +seta r_ext_compress_textures "1" +seta r_ext_compress_lightmaps "0" +seta r_ext_preferred_tc_method "0" +seta r_ext_gamma_control "1" +seta r_ext_multitexture "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_texture_env_add "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_picmip "1" +seta r_detailtextures "1" +seta r_texturebits "0" +seta r_texturebitslm "0" +seta r_colorbits "32" +seta r_stereo "0" +seta r_stencilbits "8" +seta r_depthbits "24" +seta r_overBrightBits "1" +seta r_ignorehwgamma "0" +seta r_mode "8" +seta r_fullscreen "0" +seta r_customwidth "1600" +seta r_customheight "1024" +seta r_customaspect "1" +seta r_simpleMipMaps "1" +seta r_vertexLight "0" +seta r_subdivisions "4" +seta r_ignoreFastPath "1" +seta r_intensity "1" +seta r_lodCurveError "250" +seta r_lodbias "0" +seta r_flares "1" +seta r_lodscale "10" +seta r_ignoreGLErrors "1" +seta r_fastsky "0" +seta r_drawSun "0" +seta r_dynamiclight "1" +seta r_dlightBacks "1" +seta r_finish "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_swapInterval "0" +seta r_gamma "1.359375" +seta r_facePlaneCull "1" +seta r_primitives "0" +seta r_showtriscolor "0" +seta cg_shadows "0" +seta r_modelpoolmegs "20" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta vid_xpos "0" +seta vid_ypos "0" +seta s_volume "0.039062" +seta s_volumeVoice "0.039062" +seta s_musicvolume "0.015625" +seta s_separation "0.5" +seta s_khz "22" +seta s_allowDynamicMusic "1" +seta s_mixahead "0.2" +seta s_mixPreStep "0.05" +seta s_language "francais" +seta s_mp3overhead "31756" +seta s_UseOpenAL "0" +seta s_soundpoolmegs "25" +seta use_ff "1" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta ff_delay "40" +seta cg_drawCrosshair "1" +seta cg_marks "1" +seta ui_menuFiles "ui/menus.txt" +seta ui_smallFont "0.25" +seta ui_bigFont "0.4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_r_glCustom "4" +seta g_subtitles "2" +seta cg_saberAutoThird "0" +seta cg_gunAutoFirst "1" +seta cg_drawSpeed "0" +seta g_spskill "0" +seta cg_crosshairForceHint "1" +seta cm_playerCurveClip "1" +seta cg_drawGun "1" +seta cg_stereoSeparation "0.4" +seta cg_draw2D "1" +seta cg_drawStatus "1" +seta cg_drawTimer "1" +seta cg_drawFPS "1" +seta cg_drawServerFPS "1" +seta cg_drawSnapshot "0" +seta cg_drawAmmoWarning "1" +seta cg_dynamicCrosshair "1" +seta cg_crosshairIdentifyTarget "1" +seta cg_crosshairSize "24" +seta cg_crosshairX "0" +seta cg_crosshairY "0" +seta cg_simpleItems "0" +seta cg_runpitch "0.002" +seta cg_runroll "0.005" +seta cg_bobup "0.005" +seta cg_bobpitch "0.002" +seta cg_bobroll "0.002" +seta cg_missionInfoCentered "1" +seta cg_reliableAnimSounds "1" +seta cg_drawSecrets "0" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawOverbounceInfo "0" +seta cg_drawJumpHelper "0" +seta cg_jumpHelperX "0" +seta cg_jumpHelperY "0" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_speedScale "0.9" +seta cg_speedX "0" +seta cg_speedY "75" +seta cg_speedColorR "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorB "1.0" +seta cg_speedColorA "0.9" +seta cg_drawStrafeHelper "0" +seta cg_strafeHelperCenter "1" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedA "0.9" +seta g_dismemberment "3" +seta g_dismemberProbabilities "1" +seta g_saberAutoBlocking "1" +seta g_saberRealisticCombat "0" +seta g_saberMoveSpeed "1" +seta g_saberAnimSpeed "1" +seta g_saberAutoAim "1" +seta g_saber_color "yellow" +seta g_speedFactorLanding "1.0" +seta ui_iscensored "0" +seta d_slowmodeath "0" +seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta r_weatherScale "1" diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 7df57e1b..2d985054 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -2034,8 +2034,8 @@ void CG_Init( int serverCommandSequence ) { cgi_AddCommand ("kill"); cgi_AddCommand ("give"); cgi_AddCommand ("god"); - // Posto : we might need that - cgi_AddCommand("randomizerdebug"); + // Posto : This is added when a map is loaded. + cgi_AddCommand("randomizer_debug"); cgi_AddCommand ("notarget"); cgi_AddCommand ("noclip"); cgi_AddCommand ("undying"); diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index b76b153a..939c18a4 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2835,27 +2835,192 @@ void PopulateNPCTab(int source) currentTabPosition++; } } -void RandomizerPrintAll() +char* GetNPCNames(int source) { - gi.Printf(S_COLOR_GREEN"We are getting to this function, we can log things here !\n"); + switch (source) + { + case 0: + return "Kyle"; + case 1: + return "Lando"; + case 2: + return "Jan"; + case 3: + return "Luke"; + case 4: + return "MonMothma"; + case 5: + return "Tavion"; + case 6: + return "Reelo"; + case 7: + return "Galak"; + case 8: + return "Desann"; + case 9: + return "Bartender"; + case 10: + return "Morgan"; + case 11: + return "Jedi"; + case 12: + return "Prisoner"; + case 13: + return "Rebel"; + case 14: + return "StormTrooper"; + case 15: + return "StormTrooperOfficier"; + case 16: + return "TiePilot"; + case 17: + return "Ugnaught"; + case 18: + return "Gran"; + case 19: + return "Rodian"; + case 20: + return "Weequay"; + case 21: + return "Trandoshan"; + case 22: + return "SwampTrooper"; + case 23: + return "Imperial"; + case 24: + return "ImpWorker"; + case 25: + return "BespinCop"; + case 26: + return "Reborn"; + case 27: + return "ShadowTrooper"; + case 28: // This entity doesn't work, retry + return "UNKNOWN"; + case 29: // This entity doesn't work, retry + return "UNKNOWN"; + case 30: // This entity doesn't work, retry + return "UNKNOWN"; + case 31: + return "MineMonster"; + case 32: // This entity doesn't work, retry + return "UNKNOWN"; + case 33: // This entity doesn't work, retry + return "UNKNOWN"; + case 34: // This entity doesn't work, retry + return "UNKNOWN"; + case 35: // This entity doesn't work, retry + return "UNKNOWN"; + case 36: // This entity doesn't work, retry + return "UNKNOWN"; + case 37: + return "DroidInterrogator"; + case 38: + return "DroidProbe"; + case 39: + return "DroidMark1"; // Chicken Robot + case 40: + return "DroidMark2"; // Small bot (found in comms) + case 41: // Attention + return "ATST"; + case 42: + return "DroidSeeker"; + case 43: + return "DroidRemote"; + case 44: + return "DroidSentry"; + case 45: + return "DroidGonk"; + case 46: + return "DroidMouse"; + case 47: + return "DroidR2D2"; + case 48: + return "DroidR5D2"; + case 49: + return "DroidProtocol"; + break; + default: // Secours + return "UNKONWN"; + } +} +void RandomizerDebugCommandCatcher(int page) +{ + // List of colors + //S_COLOR_BLACK, S_COLOR_BLUE, S_COLOR_CYAN, S_COLOR_GREEN, S_COLOR_MAGENTA, S_COLOR_RED, S_COLOR_WHITE, S_COLOR_YELLOW + + //gi.Printf(S_COLOR_GREEN"We are getting to this function, we can log things here !\n"); + //gi.Printf(S_COLOR_GREEN"Page number received : %d\n",page); + + // Just for information : the console is 30 lines long, + if (page <= 0 || page >= 5) // The help page, when we reach an undefined number. + { + gi.Printf(S_COLOR_RED"Oops, it seems that you didn't provide a valid page number.\n"); + gi.Printf(S_COLOR_RED"Welcome to the default page.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the correct syntax : randomizer_debug .\n"); + gi.Printf(S_COLOR_WHITE"Page 1 : General information.\n"); + gi.Printf(S_COLOR_WHITE"Page 2 : Currently generated NPCs on this map (%s).\n",level.mapname); + gi.Printf(S_COLOR_WHITE"Page 3 : Rules for NPCs.\n"); + gi.Printf(S_COLOR_WHITE"Page 4 : Rules for maps.\n"); + gi.Printf(S_COLOR_WHITE"Page 5+ : Todo\n"); + return; // So that we won't go to the switch bellow + } + switch (page) + { + case 1: // General informations + gi.Printf(S_COLOR_MAGENTA"Todo ?\n"); + break; + case 2: // Informations about tabLockedInNPC + gi.Printf(S_COLOR_MAGENTA"The maximum number of unique NPCs authorized is currently %d.\n",tabSize); + gi.Printf(S_COLOR_MAGENTA"The map is : %s.\n", level.mapname); + for (int i = 0; i < tabSize; i++) + { + gi.Printf(S_COLOR_CYAN"NPC number %d is : %s.\n",i+1 ,GetNPCNames(tabLockedInNPC[i])); + } + break; + case 3: // Which NPC are forced no matter which map (Jan for exemple, not having her breaks the first map and yavin_swamp cutscene as far as I know). Update this if needed + gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now thta's how it is.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will ALWAYS spawn as themselves, no matter which map you are on :\n"); + gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, R2D2, R5D2 and SeekerDrones.\n"); + break; + case 4: // Map specific locked NPCs (thinking about the officer in assembly to open the first door)(maybe other NPCs can do it, but idk). Update this if needed. + gi.Printf(S_COLOR_MAGENTA"Some spawn on specific maps are forced, so that we don't softlock the game.\n"); + gi.Printf(S_COLOR_MAGENTA"Unfortunatly, it means that every iteration of the same NPC on this map will spawn normally.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of maps that have specific NPC locked :\n"); + gi.Printf(S_COLOR_CYAN"Todo.\n"); + break; + default: + return; + } + } void SP_NPC_Spawn_Random(gentity_t* self) { // Pas besoin de srand puisqu'il est call déjà sur g_main.cpp (???????) - // Modulo de 49 car il y a 49 entités si j'ai bien compté. +1 pour skip Kyle, même si avoir 2 Kyle n'est potentiellement pas un problème. int rng = rand() % 50 ; - // Idée d'Amber : limiter le nombre de NPc plutôt que de modifier d'autres valeurs in game qui peuvent potentiellement faire crash le jeu. + + // Idée d'Amber : limiter le nombre de NPC plutôt que de modifier d'autres valeurs in game qui peuvent potentiellement faire crash le jeu. // Du coup, tableau de 10 emplacements déclaré plus haut afin de faire mes tests. //string messageToWrite = "Random NPC Spawn, number generated is : "+std::to_string(rng)+"\n"; //gi.Printf(S_COLOR_YELLOW,messageToWrite.c_str()); // We can't catch that, too much logging between that and the moment we have access to the console. // Case : We have a duplicate in our locking NPC array, and we want to have different NPCs - while (IsThereDuplicateInTab(rng) && currentTabPosition!=tabSize) + // This can be commented if in the future we find a way to have any kind of NPC to spawn without restiction + while (IsThereDuplicateInTab(rng) && currentTabPosition!=tabSize && tabSize!=50) { rng = rand() % 50; } + + // Let's suppose we find a way to have any kind of NPC, we can authorize anything in our big array, so that we don't have to change "much" of the code. + /* + if (tabSize == 50) + { + for (int i = 0; i < tabSize; i++) tabLockedInNPC[i] = i; + } + */ + // Case : We already have 10 NPC loaded, so we want to roll one of them. This can take time, but only during a map load. while ((currentTabPosition == tabSize && !IsRNGInTab(rng))) { @@ -3324,7 +3489,7 @@ void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self CheckIfMapChanged(); SP_NPC_Droid_R2D2(self); } -void SP_NPC_Droid_R5D2_Random(gentity_t* self) +void SP_NPC_Droid_R5D2_Random(gentity_t* self) // R5D2 should spawn as self { CheckIfMapChanged(); SP_NPC_Droid_R5D2(self); diff --git a/code/game/g_cmds.cpp b/code/game/g_cmds.cpp index 2967eab0..c50be688 100644 --- a/code/game/g_cmds.cpp +++ b/code/game/g_cmds.cpp @@ -7,7 +7,7 @@ #include "wp_saber.h" //#include <..\game\NPC_spawn.cpp> -extern void RandomizerPrintAll(); // It's declared in NPC_spawn.cpp +//extern void RandomizerDebugCommandCatcher(int page); // It's declared in NPC_spawn.cpp extern bool in_camera; @@ -1033,11 +1033,13 @@ void ClientCommand( int clientNum ) { return; } - // Posto : maybe adding a command is here ? + // Posto : maybe adding a command is here ? No, this is called later if (Q_stricmp(cmd, "give") == 0) Cmd_Give_f(ent); - else if (Q_stricmp(cmd, "randomizerdebug") == 0) - RandomizerPrintAll(); + /* + else if (Q_stricmp(cmd, "randomizer_debug") == 0) + RandomizerDebugCommandCatcher(); + */ else if (Q_stricmp (cmd, "god") == 0) Cmd_God_f (ent); else if (Q_stricmp (cmd, "undying") == 0) diff --git a/code/game/g_svcmds.cpp b/code/game/g_svcmds.cpp index 936786b5..fb06bd8f 100644 --- a/code/game/g_svcmds.cpp +++ b/code/game/g_svcmds.cpp @@ -8,7 +8,7 @@ #include "wp_saber.h" //#include <..\game\NPC_spawn.cpp> -extern void RandomizerPrintAll(); // It's declared in NPC_spawn.cpp +extern void RandomizerDebugCommandCatcher(int page); // It's declared in NPC_spawn.cpp extern void Q3_SetViewEntity(int entID, const char *name); extern qboolean G_ClearViewEntity( gentity_t *ent ); @@ -927,11 +927,14 @@ qboolean ConsoleCommand( void ) { Svcmd_ExitView_f(); } - // Posto : Maybe adding a command is here ? - if (Q_stricmp(cmd, "randomizerdebug") == 0) + // Posto : This is caught first + if (Q_stricmp(cmd, "randomizer_debug") == 0) { - - RandomizerPrintAll(); + // After randomizer_debug, we want to catch the first arg. If not set (page is a 0 size char array), send page -1 (equivalent to a help page) + // Does that mean that a page 0 exist ? No, if a page is not referenced, we print the help page. + char* page = gi.argv(1); + if (strlen(page)==0) RandomizerDebugCommandCatcher(-1); // Show the 'help page' + else RandomizerDebugCommandCatcher(atoi(page)); } return qfalse; From 055fad533f8e85c2d495665687e3928b00638683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Sun, 6 Oct 2024 17:56:00 +0200 Subject: [PATCH 07/62] Push of what I did today. Note : with a limit of 10 NPC, I managed to get a full playthrough without crashes. I did find some softlock that need to be fixed. --- Posto-Stuff-ReadmePLZ.txt | 14 ++++++-- code/game/NPC_spawn.cpp | 65 ++++++++++++++++++++++++-------------- code/qcommon/stv_version.h | 6 ++-- 3 files changed, 57 insertions(+), 28 deletions(-) diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index 51871224..5e918a4a 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -66,9 +66,10 @@ CURRENT SITUATION : I locked the number of max unique NPC to 10 for now. In DEBUG, the game is way less permissing and throw errors often. But in RELEASE ? It seems plyable, I will do a full playthrought to confirm that. -I tried to do entire playthought, here is a list of softlock I had (stopped at topside) : +I DID an entire playthought without ATST, and a max of 10 random unique NPC, here is a list of softlock I had : +Chicken robots are really too big, I think we should make them spawn naturally and not randomly. - Two or more NPC spawn location being too close is a problem, if for exemple ATSTs tried to spawn, only one will THEN the other when there is enough space -- kejim_base : the NPC that spawned behind the door could'nt spawn, it was a big droid. Making it impossible for the cutscene to execute +- kejim_base : the NPC that spawned behind the door couldn't spawn, it was a big droid and Reelo. Making it impossible for the cutscene to execute - artus_detention : NPC will NOT respect that truce when the guard is activated, not really a softlock but careful. Also, any NPC can trigger the guard, not only Kyle. The guard being too big will not work. @@ -76,3 +77,12 @@ Fortunatly, no matter which team the NPC spawned, it will be overwritten and wil - artus_topside : Didn't manage to load the map under unknown conditions The path finding of NPC that spawn instead of the stormtrooper seems to always be broken +- ns_starpad crashes during the final against Reelo, I should retry this +- cairn_assembly : if the imperial opening the door is too small (for exmeple a small droid), you can't reach the hitbox to hit persuasion +If the NPC remplacin the two reborn dies or don't spawn (don't know which), the ATST door won't open. +- cairn_dock : the map is imposible to play because the new NPCs are having undefefined behavior, making the discretion impossible and you are spoted instantly when by the window +The shadowtropper have to spawn as a shadowtrooper I think because the platform where it spawns DON'T ELEVATE other NPCs (humanoid or droids) +- doom_detention : I didn't any problem with the guard opening the doors, but there might be the same problem as cairn_assembly + + + diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 939c18a4..70ee98da 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2785,8 +2785,12 @@ void SP_NPC_Droid_Protocol( gentity_t *self) // The Posto is for faster search so I know what I edited -const int tabSize = 10; -short tabLockedInNPC[tabSize] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +const int tabSize = 50; +short tabLockedInNPC[tabSize]={ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; short currentTabPosition = 0; char lastKnownMap[32] = "first_iteration"; @@ -2968,20 +2972,29 @@ void RandomizerDebugCommandCatcher(int page) switch (page) { case 1: // General informations - gi.Printf(S_COLOR_MAGENTA"Todo ?\n"); + gi.Printf(S_COLOR_MAGENTA"NPC spawns are determined during the first load of a map. Meaning that if youn load a map, quicksave and quickload, the NPCs will always be the sames.\n"); + gi.Printf(S_COLOR_MAGENTA"But, if you reload the map using the save files that the game generate, a new set of random NPCs will be generated.\n"); + gi.Printf(S_COLOR_MAGENTA"All random NPCs remplacing ones carrying keys to open doors (eg : kejim_base), will also carry said keys. So kill them to get keys (even if they are friendly or neutral) !\n"); break; case 2: // Informations about tabLockedInNPC gi.Printf(S_COLOR_MAGENTA"The maximum number of unique NPCs authorized is currently %d.\n",tabSize); gi.Printf(S_COLOR_MAGENTA"The map is : %s.\n", level.mapname); - for (int i = 0; i < tabSize; i++) + if (tabSize != 50) { - gi.Printf(S_COLOR_CYAN"NPC number %d is : %s.\n",i+1 ,GetNPCNames(tabLockedInNPC[i])); + for (int i = 0; i < tabSize; i++) + { + gi.Printf(S_COLOR_CYAN"NPC number %d is : %s.\n", i + 1, GetNPCNames(tabLockedInNPC[i])); + } } + else gi.Printf(S_COLOR_CYAN"ALL NPC can spawn (except the ones banned do to them being unstable / broken).\n"); + break; case 3: // Which NPC are forced no matter which map (Jan for exemple, not having her breaks the first map and yavin_swamp cutscene as far as I know). Update this if needed gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now thta's how it is.\n"); gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will ALWAYS spawn as themselves, no matter which map you are on :\n"); - gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, R2D2, R5D2 and SeekerDrones.\n"); + gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, ATST, Mark1, Mark2 (Chicken robot), R2D2, R5D2 and SeekerDrones.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will NEVER randomly spawn, no matter which map you are on :\n"); + gi.Printf(S_COLOR_CYAN""); break; case 4: // Map specific locked NPCs (thinking about the officer in assembly to open the first door)(maybe other NPCs can do it, but idk). Update this if needed. gi.Printf(S_COLOR_MAGENTA"Some spawn on specific maps are forced, so that we don't softlock the game.\n"); @@ -3014,12 +3027,12 @@ void SP_NPC_Spawn_Random(gentity_t* self) } // Let's suppose we find a way to have any kind of NPC, we can authorize anything in our big array, so that we don't have to change "much" of the code. - /* + if (tabSize == 50) { for (int i = 0; i < tabSize; i++) tabLockedInNPC[i] = i; } - */ + // Case : We already have 10 NPC loaded, so we want to roll one of them. This can take time, but only during a map load. while ((currentTabPosition == tabSize && !IsRNGInTab(rng))) @@ -3193,18 +3206,21 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_Droid_Probe(self); PopulateNPCTab(rng); break; - case 39: - SP_NPC_Droid_Mark1(self); - PopulateNPCTab(rng); + case 39: // Chicken robot are way too big, let's keep them out + //SP_NPC_Droid_Mark1(self); + //PopulateNPCTab(rng); + SP_NPC_Spawn_Random(self); break; - case 40: - SP_NPC_Droid_Mark2(self); - PopulateNPCTab(rng); + case 40: // Chicken robot are way too big, let's keep them out + //SP_NPC_Droid_Mark2(self); + //PopulateNPCTab(rng); + SP_NPC_Spawn_Random(self); break; - case 41: // Attention - SP_NPC_Droid_ATST(self); - PopulateNPCTab(rng); + case 41: // ATST are very buggy, let's keep them out for the moment + //SP_NPC_Droid_ATST(self); + //PopulateNPCTab(rng); //SP_NPC_Stormtrooper(self); + SP_NPC_Spawn_Random(self); break; case 42: SP_NPC_Droid_Seeker(self); @@ -3444,20 +3460,23 @@ void SP_NPC_Droid_Probe_Random(gentity_t* self) // Who is that ? CheckIfMapChanged(); SP_NPC_Spawn_Random(self); } -void SP_NPC_Droid_Mark1_Random(gentity_t* self) // Who is that ? +void SP_NPC_Droid_Mark1_Random(gentity_t* self) // Chicken robot, make then static and not in the random pool (they are big). Wait, two chicken robot entities ? { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Droid_Mark1(self); } -void SP_NPC_Droid_Mark2_Random(gentity_t* self) // Who is that ? +void SP_NPC_Droid_Mark2_Random(gentity_t* self) // Chicken robot, make then static and not in the random pool (they are big). Wait, two chicken robot entities ? { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Droid_Mark2(self); } -void SP_NPC_Droid_ATST_Random(gentity_t* self) +void SP_NPC_Droid_ATST_Random(gentity_t* self) // Since they are buggy, let's keep the one existing intact. { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Droid_ATST(self); } void SP_NPC_Droid_Seeker_Random(gentity_t* self) // Seekers should always be seekers, at least in speedruns { diff --git a/code/qcommon/stv_version.h b/code/qcommon/stv_version.h index 46bc2a62..8521f35c 100644 --- a/code/qcommon/stv_version.h +++ b/code/qcommon/stv_version.h @@ -2,11 +2,11 @@ #include "../win32/autoversion.h" #ifdef _DEBUG - #define Q3_VERSION "(debug) Speed Outcast: v"VERSION_STRING_DOTTED + #define Q3_VERSION "(debug) Speed Outcast (Randomizer): v"VERSION_STRING_DOTTED #elif defined FINAL_BUILD - #define Q3_VERSION "Speed Outcast: v"VERSION_STRING_DOTTED + #define Q3_VERSION "Speed Outcast (Randomizer): v"VERSION_STRING_DOTTED #else - #define Q3_VERSION "(internal) Speed Outcast: v"VERSION_STRING_DOTTED + #define Q3_VERSION "(internal) Speed Outcast (Randomizer): v"VERSION_STRING_DOTTED #endif // end From d25bc7f2d2cb88c3b253697a42fa24184372990d Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sun, 6 Oct 2024 23:17:07 +0100 Subject: [PATCH 08/62] Add Randomizer menus in pk3 and add seeded randomness Still not ideal as random seed is only updated on game launch for now - need to do so when new game button is clicked. --- code/cgame/cg_draw.cpp | 16 ++++++++++++++++ code/cgame/cg_local.h | 4 ++++ code/cgame/cg_main.cpp | 16 ++++++++++++++++ code/demo/assets_randomizer.pk3 | Bin 0 -> 15225 bytes code/game/NPC_spawn.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 code/demo/assets_randomizer.pk3 diff --git a/code/cgame/cg_draw.cpp b/code/cgame/cg_draw.cpp index 8d4eb1e6..b46c8109 100644 --- a/code/cgame/cg_draw.cpp +++ b/code/cgame/cg_draw.cpp @@ -2336,6 +2336,18 @@ static float CG_DrawSecrets( float y ) { return y + BIGCHAR_HEIGHT + 10; } +/* +=============== +CG_DrawSeed +=============== +*/ +static float CG_DrawSeed(float y) { + const char* seed_string = va("Seed: %s", cg_setSeed.string); + const int width = cgi_R_Font_StrLenPixels(seed_string, cgs.media.qhFontMedium, 1.0f); + cgi_R_Font_DrawString(635 - width, y + 2, seed_string, colorTable[CT_LTGOLD1], cgs.media.qhFontMedium, -1, 1.0f); + return y + BIGCHAR_HEIGHT + 10; +} + static float jumpHelperGetRangeExtendingLength(const int force_jump_level) { // TODO: This actually depends on FPS (or rather frametime in pmove)... extern float forceJumpHeight[]; @@ -2692,6 +2704,10 @@ static void CG_Draw2D( void ) { CG_DrawOverbounceInfo(); } + if ( cg_drawSeed.integer ) + { + CG_DrawSeed(y); + } // don't draw center string if scoreboard is up if ( !CG_DrawScoreboard() ) { diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index cfa26a32..d2755fe3 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -693,6 +693,10 @@ extern vmCvar_t cg_strafeHelperColorSpeedG; extern vmCvar_t cg_strafeHelperColorSpeedB; extern vmCvar_t cg_strafeHelperColorSpeedA; +//Additions for Randomizer +extern vmCvar_t cg_drawSeed; +extern vmCvar_t cg_setSeed; + void CG_NewClientinfo( int clientNum ); // // cg_main.c diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 2d985054..aa309d5b 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -390,6 +390,11 @@ vmCvar_t cg_strafeHelperColorSpeedG; vmCvar_t cg_strafeHelperColorSpeedB; vmCvar_t cg_strafeHelperColorSpeedA; +// Additions for Randomizer +vmCvar_t cg_drawSeed; +vmCvar_t cg_useSetSeed; +vmCvar_t cg_setSeed; + typedef struct { vmCvar_t *vmCvar; char *cvarName; @@ -573,6 +578,11 @@ Ghoul2 Insert End { &cg_strafeHelperColorSpeedG, "cg_strafeHelperColorSpeedG", "1.0", CVAR_ARCHIVE }, { &cg_strafeHelperColorSpeedB, "cg_strafeHelperColorSpeedB", "1.0", CVAR_ARCHIVE }, { &cg_strafeHelperColorSpeedA, "cg_strafeHelperColorSpeedA", "0.9", CVAR_ARCHIVE }, + + // Additions for Randomizer + { &cg_drawSeed, "cg_drawSeed", "0", CVAR_ARCHIVE }, + { &cg_useSetSeed, "cg_useSetSeed", "", CVAR_ARCHIVE }, + { &cg_setSeed, "cg_setSeed", "", CVAR_ARCHIVE } }; int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); @@ -1963,6 +1973,12 @@ Ghoul2 Insert End CG_RegisterCvars(); + //Reinitialise randomizer seed value if we're not using setSeed + if (cg_useSetSeed.value != 1) + { + *cg_setSeed.string = time(NULL); //bit cheeky but we should be doing this before anything else can touch the value + } + //moved from CG_GameStateReceived because it's loaded sooner now CG_InitLocalEntities(); diff --git a/code/demo/assets_randomizer.pk3 b/code/demo/assets_randomizer.pk3 new file mode 100644 index 0000000000000000000000000000000000000000..2799209b8b780fcec38e01efa791aa20359ad070 GIT binary patch literal 15225 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%0A$8Dfa9 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 Cfl^@r literal 0 HcmV?d00001 diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 70ee98da..637e6177 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -59,6 +59,9 @@ extern void NPC_GalakMech_Init( gentity_t *ent ); extern void NPC_Protocol_Precache( void ); extern int WP_SetSaberModel( gclient_t *client, class_t npcClass ); +extern vmCvar_t cg_useSetSeed; +extern vmCvar_t cg_setSeed; + #define NSF_DROP_TO_FLOOR 16 @@ -2794,6 +2797,14 @@ short tabLockedInNPC[tabSize]={ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, short currentTabPosition = 0; char lastKnownMap[32] = "first_iteration"; +//I hate working in c++ so much +void AddCharArrayToInt(char chars[], int* value) +{ + for (int i = 0; i < sizeof(chars); i++) { + *value += chars[i]; + } +} + void MapChanged() { //strcpy(lastKnownMap, level.mapname); @@ -2806,7 +2817,20 @@ void MapChanged() // We might have to lock Kyle, we will see what happen. // tabLockedInNPC[0] = 0; // currentTabPosition = 1; + + // We want to ensure seed consistenty per level + // i.e. for a given seed a player will always get the same enemy spawn for that level + // regardless of any other uses of rand() in the game. Thus we should set the seed + // on level change, and use the level string as a part of the seed to get + // unique enemy sets per level + if (cg_setSeed.string != "") { //If we have no set seed just use random seed -- should we warn user? + int seed = 0; + AddCharArrayToInt(cg_setSeed.string, &seed); + AddCharArrayToInt(level.mapname, &seed); + srand(seed); + } } + void CheckIfMapChanged() { if (strcmp(lastKnownMap, level.mapname) != 0) From a6004c2ba70219dd96d819bc381ad7c7f03485ea Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 7 Oct 2024 19:05:20 +0100 Subject: [PATCH 09/62] Removed randomizer_debug content from menus --- code/demo/assets_randomizer.pk3 | Bin 15225 -> 15134 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/code/demo/assets_randomizer.pk3 b/code/demo/assets_randomizer.pk3 index 2799209b8b780fcec38e01efa791aa20359ad070..7f820a85def8e627800328cb122442ce1f019a4b 100644 GIT binary patch delta 1463 zcmexaHm_`gHlOSa_ejTg#d7zh85kxrZM4*sst@#UcHn9F?{#?dNA@3SC7m-~2+h>r zxACpSjDx!60>brsa}%3_{n&XwdK{B;yMA|F{Oo(N-U18%DkQZQG{;O0KiDs8vbBR( zW!{m;-k%+he{Y_8@9noPCQU(pS6BA=3xqu^)*P>xD&@}HTd3D8=^J2H{gO9e7_nw8UxbLnsn{nGr)kDkJ3!0+-N*%a#q|@u_zXd%! z?P~&J55U^a%e9um4Wy$qxo1<@Mt4uXuI6ZOhtNQw5pSGUjZwk1#*ve&6 z+heuKEUG)dsQAj9RlUg_G%rEYf_;N#V7~p?S1WA4?>g4o(*7a!;}`$%%;hIJnKoUm z{I>4QOu2~V>V0oqv@B;HJk=w!YHo&tHiKzF4$rQ}{?$h6nJa`GwN(?Vw{b;k|E@S3 ze`I&kk)Mt63o-ECp*k@z}eUHsME5_3cC^S0h|+i}3PyKlYti@b;1w;j6lf0w3O z`l@Fqc1dXjy$D$b|IQ1h?dKg9UEebAn2LnStQAJR8P3;cI6W8J zvG3X4?Uy~)O|^-4-~1?aS?l#e)roiF-|wkX(0S2t(NUj!VYkh;pcNvqcjMZB^hjlk zCe`No|NXqEep1VB&I=1{}pSVh38OQ8DQXy)luaxQ!olM!;zBBb;m%Xj5 zL}i$g+@zjwXBqAv^xOGUV*jMacOC9o#y2IZpR``{`i9yp&2JXxB4e`p9UC4p*2^e#doycXt~mbfO+nI1X}-|b53yGxniuIU?%EM3@geff zV$+FJzABcye)aE_XX^APhvwZamDF^sxBRho79= zpElJQPh=PO$+{tTvvGfo5_>;yz?6<+wa|$RHA@8f%!6*UAGrCqX6c>p(Ol9TBECN= zb;1f7Z_LYFw4rHJboI^6Ea!Bme!JJzbed}+<7@p$hxk8#SSNc~C88CRlXqGfJI}nN zd*_kFZAKVvtQ=FJ4CDuRGcwsT;L2_)zzhch3P5Z)S>IYlFZVV3RggI_I=&EQ4l5f- PB{L98GBPl{w*>J3s4J%$ delta 1524 zcmVh2Ub|q1_JbKKggfLa zxe01JXfhESNIZ$BFU<#~xgX5+X0uo1NQroeQ`-0h9YV-%eSt@!@opeD&UMh?2?#Cr zo?E2hF6}j7_OK{_$}I8LS85lBS`NYKNiR%LaRY^g6bXsI*q4-=14eCtYzw*=Lo$wu zIEo+={jw;PMf;6K=1mU48GW|_JU%DG+mH(Nn@D6czPRKDz_Me1r~03<{79pNAe0ZN4w0nW zag#}cl3eyAOzg}h*$cKjz%p>QU{j*r-p}f&*!Q}{M8f0bZT#|2S83JY1OZv=X!oVe zg)=YRIQ;#8gxmCq-cy?g7x*E=wp7?5e?<-+2jD2N$eCmj-xNxO!%hmj5I7!9=Ip-D zDRdBMo%r>)`Sb^3L=_Q*3aW1HbE{$~&r~XvvPUj`118aadIGG%*Evb=Yqd-_Z8)p( zbkBw=S4O0>uD?ojYbt!x)Dvt>Qm_4 z0M~QgeLaojQpxkBKgnKYnt2^t63OlL&Wi`af(~dM^t=$dNMkFBO4il&b%-yhF;*c~ z=eE>8&nkZjxjoZ&O#*#3*LEMVIEg}tIXni>A&@XZJ-ZLNf!X({hu(wLr^4tm4$sWr zlGV2pMt{TN=|HiGT>AqpZ9#U6=ny$3isb4ljpWGnsn>p>uL-<6N=+Vn%iGLr6l{%# zp8KN~C!9};lF)3beBfjMfiEkB5yBRK9~34vsv>{F%4E5Nxn+X|-|Y^JJS!0oVM6<6 zfNxSl2O4G?VOcoH1VEt*;r)8{0#0ey$g$SaAu3x)c?% z0;4M{Hx)4Q2&iv?>o%m$iH?EXNjGqD!KMz2k~ez@`gCpycy#PDf9t+3iLx7D^DKz4 z?g4-7Ad5=@7)QaD?b+ePB0C()3gM@$u>?g`Mi#N7FyOM-M{Oc0>qDs4RsGeH$|lK$ zEww{xWBD&Ro-9K73#&sU>2|8gq=GiNbR
gSMSi!bp2mbPf96UBaRw785 zltsFx&_+01NnslTC*$cty6@K%RuCwv@N-zK;0m!lQ$%3}dAIhmXCYi#D($@$8J9O* z17<_A;0#y+U;4qHHf)vbns8R&>3&DFw`EK<7EU_lFKfr)eYn3^**0>`GC$mll?jy21+^r0001uz`Zg6 From f4b1615c86c6d9adbc7510be8f6230dd7baabb8d Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 7 Oct 2024 20:11:19 +0100 Subject: [PATCH 10/62] Random Seed now generates a fixed length 9 digit string and displays correctly --- code/cgame/cg_main.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index aa309d5b..50199348 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -24,6 +24,8 @@ extern void CG_RegisterNPCEffects( team_t team ); extern qboolean G_ParseAnimFileSet( const char *filename, const char *animCFG, int *animFileIndex ); extern void CG_DrawDataPadInventorySelect( void ); +using namespace std::chrono; + void CG_Init( int serverCommandSequence ); qboolean CG_ConsoleCommand( void ); void CG_Shutdown( void ); @@ -1976,7 +1978,28 @@ Ghoul2 Insert End //Reinitialise randomizer seed value if we're not using setSeed if (cg_useSetSeed.value != 1) { - *cg_setSeed.string = time(NULL); //bit cheeky but we should be doing this before anything else can touch the value + //Get System Epoch Time + auto duration = system_clock::now().time_since_epoch(); + + //Convert duration to milliseconds + long milliseconds + = chrono::duration_cast( + duration) + .count(); + + //Hash the time to get a consistent length seed + hash hasher; + string s = to_string(milliseconds); + size_t hash = hasher(s); + + //Convert to string to make next conversion easier + string hashString = to_string(hash); + + //Copy the value in hashString into cg_setSeed for use later + //I can't believe there's no better way to do this + for (int i = 0; i < 9; i++) { + cg_setSeed.string[i] = hashString.at(i); + } } //moved from CG_GameStateReceived because it's loaded sooner now From a7790db018f1e8359dcce673e3aa318e527a023f Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 7 Oct 2024 20:27:18 +0100 Subject: [PATCH 11/62] temp fix to reduce repeater missile spam to make crashes less frequent --- code/game/g_missile.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/code/game/g_missile.cpp b/code/game/g_missile.cpp index eccb6e2e..106a742a 100644 --- a/code/game/g_missile.cpp +++ b/code/game/g_missile.cpp @@ -42,6 +42,21 @@ void G_MissileBounceEffect( gentity_t *ent, vec3_t org, vec3_t dir ) G_PlayEffect( "blaster/deflect", ent->currentOrigin, dir ); #endif // _IMMERSION break; + //Amber this should be a temp fix, we really need to figure out how to up GENTITYNUM_BITS value safely + case WP_REPEATER: //Reduce missile spam created by repeaters to reduce risk of going over entity limit + if (rand() % 2 == 0) { + gentity_t* tent = G_TempEntity(org, EV_GRENADE_BOUNCE); + VectorCopy(dir, tent->pos1); + tent->s.weapon = ent->s.weapon; +#ifdef _IMMERSION + if (hitEntNum != -1) + { + tent->s.saberActive = 1; + tent->s.otherEntityNum = hitEntNum; + } + } + break; +#endif // _IMMERSION default: { gentity_t *tent = G_TempEntity( org, EV_GRENADE_BOUNCE ); From be28d86e5e4b8660e64c11c448ae852ebab2c543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Wed, 16 Oct 2024 14:23:32 +0200 Subject: [PATCH 12/62] Added weapons and ammo randomizer on item racks. --- code/base/jk2config.cfg | 473 +++++++++++++++++++------------------ code/game/NPC_spawn.cpp | 12 +- code/game/g_client.cpp | 9 +- code/game/g_itemLoad.cpp | 11 +- code/game/g_items.h | 16 +- code/game/g_misc_model.cpp | 12 + code/game/g_weaponLoad.cpp | 75 ++++++ 7 files changed, 353 insertions(+), 255 deletions(-) diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index f57e7051..68a4e61f 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -69,239 +69,242 @@ bind MOUSE5 "+force_lightning" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta com_maxfps "125" -seta sp_language "1" -seta in_midi "0" -seta in_midiport "1" -seta in_midichannel "1" -seta in_mididevice "0" -seta in_mouse "-1" -seta in_mouse_raw "1" -seta in_joystick "0" -seta in_joyBallScale "0.02" -seta joy_threshold "0.15" -seta js_ffmult "3.0" -seta joy_xbutton "1" -seta joy_ybutton "0" -seta sv_speedrunModeIL "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_timedCheckpointMinX "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxZ "0" -seta conAlpha "1.6" -seta panoNumShots "10" -seta cl_yawspeed "140" -seta cl_pitchspeed "140" -seta cl_anglespeedkey "1.5" -seta cl_maxpackets "30" -seta cl_packetdup "1" -seta cl_run "1" -seta sensitivity "5" -seta cl_mouseAccel "0" -seta cl_freelook "1" -seta cl_ingameVideo "1" -seta cl_VideoQuality "0" -seta cg_autoswitch "0" -seta m_pitch "0.022" -seta m_yaw "0.022" -seta m_forward "0.25" -seta m_side "0.25" -seta m_filter "0" -seta name "Kyle" -seta snaps "20" -seta sex "male" -seta handicap "100" -seta r_allowExtensions "1" -seta r_ext_compress_textures "1" -seta r_ext_compress_lightmaps "0" -seta r_ext_preferred_tc_method "0" -seta r_ext_gamma_control "1" -seta r_ext_multitexture "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_texture_env_add "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_picmip "1" -seta r_detailtextures "1" -seta r_texturebits "0" -seta r_texturebitslm "0" -seta r_colorbits "32" -seta r_stereo "0" -seta r_stencilbits "8" -seta r_depthbits "24" -seta r_overBrightBits "1" -seta r_ignorehwgamma "0" -seta r_mode "8" -seta r_fullscreen "0" -seta r_customwidth "1600" -seta r_customheight "1024" -seta r_customaspect "1" -seta r_simpleMipMaps "1" -seta r_vertexLight "0" -seta r_subdivisions "4" -seta r_ignoreFastPath "1" -seta r_intensity "1" -seta r_lodCurveError "250" -seta r_lodbias "0" -seta r_flares "1" -seta r_lodscale "10" -seta r_ignoreGLErrors "1" -seta r_fastsky "0" -seta r_drawSun "0" -seta r_dynamiclight "1" -seta r_dlightBacks "1" -seta r_finish "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_swapInterval "0" -seta r_gamma "1.359375" -seta r_facePlaneCull "1" -seta r_primitives "0" -seta r_showtriscolor "0" -seta cg_shadows "0" -seta r_modelpoolmegs "20" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta vid_xpos "0" -seta vid_ypos "0" -seta s_volume "0.039062" -seta s_volumeVoice "0.039062" -seta s_musicvolume "0.015625" -seta s_separation "0.5" -seta s_khz "22" -seta s_allowDynamicMusic "1" -seta s_mixahead "0.2" -seta s_mixPreStep "0.05" -seta s_language "francais" -seta s_mp3overhead "31756" -seta s_UseOpenAL "0" -seta s_soundpoolmegs "25" -seta use_ff "1" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta ff_delay "40" -seta cg_drawCrosshair "1" -seta cg_marks "1" -seta ui_menuFiles "ui/menus.txt" -seta ui_smallFont "0.25" -seta ui_bigFont "0.4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_r_glCustom "4" -seta g_subtitles "2" -seta cg_saberAutoThird "0" -seta cg_gunAutoFirst "1" -seta cg_drawSpeed "0" -seta g_spskill "0" -seta cg_crosshairForceHint "1" -seta cm_playerCurveClip "1" -seta cg_drawGun "1" -seta cg_stereoSeparation "0.4" -seta cg_draw2D "1" -seta cg_drawStatus "1" -seta cg_drawTimer "1" -seta cg_drawFPS "1" -seta cg_drawServerFPS "1" -seta cg_drawSnapshot "0" -seta cg_drawAmmoWarning "1" -seta cg_dynamicCrosshair "1" -seta cg_crosshairIdentifyTarget "1" -seta cg_crosshairSize "24" -seta cg_crosshairX "0" -seta cg_crosshairY "0" -seta cg_simpleItems "0" -seta cg_runpitch "0.002" -seta cg_runroll "0.005" -seta cg_bobup "0.005" -seta cg_bobpitch "0.002" -seta cg_bobroll "0.002" -seta cg_missionInfoCentered "1" -seta cg_reliableAnimSounds "1" -seta cg_drawSecrets "0" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawOverbounceInfo "0" -seta cg_drawJumpHelper "0" -seta cg_jumpHelperX "0" -seta cg_jumpHelperY "0" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_speedScale "0.9" -seta cg_speedX "0" -seta cg_speedY "75" -seta cg_speedColorR "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorB "1.0" -seta cg_speedColorA "0.9" -seta cg_drawStrafeHelper "0" -seta cg_strafeHelperCenter "1" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedA "0.9" -seta g_dismemberment "3" -seta g_dismemberProbabilities "1" -seta g_saberAutoBlocking "1" -seta g_saberRealisticCombat "0" -seta g_saberMoveSpeed "1" -seta g_saberAnimSpeed "1" -seta g_saberAutoAim "1" -seta g_saber_color "yellow" -seta g_speedFactorLanding "1.0" -seta ui_iscensored "0" -seta d_slowmodeath "0" -seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta cg_setSeed "7898612456" +seta cg_useSetSeed "0" +seta cg_drawSeed "1" seta r_weatherScale "1" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" +seta d_slowmodeath "0" +seta ui_iscensored "0" +seta g_speedFactorLanding "1.0" +seta g_saber_color "yellow" +seta g_saberAutoAim "1" +seta g_saberAnimSpeed "1" +seta g_saberMoveSpeed "1" +seta g_saberRealisticCombat "0" +seta g_saberAutoBlocking "1" +seta g_dismemberProbabilities "1" +seta g_dismemberment "3" +seta cg_strafeHelperColorSpeedA "0.9" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperCenter "1" +seta cg_drawStrafeHelper "0" +seta cg_speedColorA "0.1" +seta cg_speedColorB "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorR "1.0" +seta cg_speedY "75" +seta cg_speedX "0" +seta cg_speedScale "0.9" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperY "0" +seta cg_jumpHelperX "0" +seta cg_drawJumpHelper "0" +seta cg_drawOverbounceInfo "0" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSecrets "0" +seta cg_reliableAnimSounds "1" +seta cg_missionInfoCentered "1" +seta cg_bobroll "0.002" +seta cg_bobpitch "0.002" +seta cg_bobup "0.005" +seta cg_runroll "0.005" +seta cg_runpitch "0.002" +seta cg_simpleItems "0" +seta cg_crosshairY "0" +seta cg_crosshairX "0" +seta cg_crosshairSize "24" +seta cg_crosshairIdentifyTarget "1" +seta cg_dynamicCrosshair "1" +seta cg_drawAmmoWarning "1" +seta cg_drawSnapshot "0" +seta cg_drawServerFPS "1" +seta cg_drawFPS "1" +seta cg_drawTimer "1" +seta cg_drawStatus "1" +seta cg_draw2D "1" +seta cg_stereoSeparation "0.4" +seta cg_drawGun "1" +seta cm_playerCurveClip "1" +seta cg_crosshairForceHint "1" +seta g_spskill "0" +seta cg_drawSpeed "0" +seta cg_gunAutoFirst "1" +seta cg_saberAutoThird "0" +seta g_subtitles "2" +seta ui_r_glCustom "4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_bigFont "0.4" +seta ui_smallFont "0.25" +seta ui_menuFiles "ui/menus.txt" +seta cg_marks "1" +seta cg_drawCrosshair "1" +seta ff_delay "40" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta use_ff "1" +seta s_soundpoolmegs "25" +seta s_UseOpenAL "0" +seta s_mp3overhead "31756" +seta s_language "francais" +seta s_mixPreStep "0.05" +seta s_mixahead "0.2" +seta s_allowDynamicMusic "1" +seta s_khz "22" +seta s_separation "0.5" +seta s_musicvolume "0.015625" +seta s_volumeVoice "0.039062" +seta s_volume "0.039062" +seta vid_ypos "0" +seta vid_xpos "0" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta r_modelpoolmegs "20" +seta cg_shadows "0" +seta r_showtriscolor "0" +seta r_primitives "0" +seta r_facePlaneCull "1" +seta r_gamma "1.359375" +seta r_swapInterval "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_finish "0" +seta r_dlightBacks "1" +seta r_dynamiclight "1" +seta r_drawSun "0" +seta r_fastsky "0" +seta r_ignoreGLErrors "1" +seta r_lodscale "10" +seta r_flares "1" +seta r_lodbias "0" +seta r_lodCurveError "250" +seta r_intensity "1" +seta r_ignoreFastPath "1" +seta r_subdivisions "4" +seta r_vertexLight "0" +seta r_simpleMipMaps "1" +seta r_customaspect "1" +seta r_customheight "1024" +seta r_customwidth "1600" +seta r_fullscreen "0" +seta r_mode "8" +seta r_ignorehwgamma "0" +seta r_overBrightBits "1" +seta r_depthbits "24" +seta r_stencilbits "8" +seta r_stereo "0" +seta r_colorbits "32" +seta r_texturebitslm "0" +seta r_texturebits "0" +seta r_detailtextures "1" +seta r_picmip "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_ext_texture_env_add "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_multitexture "1" +seta r_ext_gamma_control "1" +seta r_ext_preferred_tc_method "0" +seta r_ext_compress_lightmaps "0" +seta r_ext_compress_textures "1" +seta r_allowExtensions "1" +seta handicap "100" +seta sex "male" +seta snaps "20" +seta name "Kyle" +seta m_filter "0" +seta m_side "0.25" +seta m_forward "0.25" +seta m_yaw "0.022" +seta m_pitch "0.022" +seta cg_autoswitch "0" +seta cl_VideoQuality "0" +seta cl_ingameVideo "1" +seta cl_freelook "1" +seta cl_mouseAccel "0" +seta sensitivity "5" +seta cl_run "1" +seta cl_packetdup "1" +seta cl_maxpackets "30" +seta cl_anglespeedkey "1.5" +seta cl_pitchspeed "140" +seta cl_yawspeed "140" +seta panoNumShots "10" +seta conAlpha "1.6" +seta sv_timedCheckpointMaxZ "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinX "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeIL "0" +seta joy_ybutton "0" +seta joy_xbutton "1" +seta js_ffmult "3.0" +seta joy_threshold "0.15" +seta in_joyBallScale "0.02" +seta in_joystick "0" +seta in_mouse_raw "1" +seta in_mouse "-1" +seta in_mididevice "0" +seta in_midichannel "1" +seta in_midiport "1" +seta in_midi "0" +seta sp_language "1" +seta com_maxfps "125" diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 637e6177..32803912 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2788,12 +2788,12 @@ void SP_NPC_Droid_Protocol( gentity_t *self) // The Posto is for faster search so I know what I edited -const int tabSize = 50; -short tabLockedInNPC[tabSize]={ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; +const short tabSize = 20; +short tabLockedInNPC[tabSize] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; + //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; short currentTabPosition = 0; char lastKnownMap[32] = "first_iteration"; diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index 9cc43af7..4193a72e 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -14,6 +14,9 @@ extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponMod extern qboolean CheatsOk( gentity_t *ent ); extern vmCvar_t cg_thirdPersonAlpha; +// Posto / Randomizer : for the first weapon (It might roll a stun baton again, would be pretty funny) +extern int GetRandomizedWeapon(); + // g_client.c -- client functions that don't happen every frame float DEFAULT_MINS_0 = -16; @@ -1597,7 +1600,9 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded // give default weapons client->ps.stats[STAT_WEAPONS] = ( 1 << WP_NONE ); - client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL ); //these are precached in g_items, ClearRegisteredItems() + // Posto : Hey, we can randomize our first weapon ! + //client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL ); //these are precached in g_items, ClearRegisteredItems() + client->ps.stats[STAT_WEAPONS] |= (1 << (weapon_t)(GetRandomizedWeapon())); client->ps.inventory[INV_ELECTROBINOCULARS] = 1; // always give the bryar pistol, but we have to give EITHER the saber or the stun baton..never both @@ -1717,7 +1722,7 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded ICARUS_FreeEnt( ent ); //FIXME: This shouldn't need to be done...? ICARUS_InitEnt( ent ); - if ( spawnPoint->spawnflags & 64 ) + if ( spawnPoint->spawnflags & 64 ) // Posto : this is the case in yavin_temple {//player starts with absolutely no weapons ent->client->ps.stats[STAT_WEAPONS] = ( 1 << WP_NONE ); ent->client->ps.ammo[weaponData[WP_NONE].ammoIndex] = 32000; // checkme diff --git a/code/game/g_itemLoad.cpp b/code/game/g_itemLoad.cpp index 753f9719..c61415b1 100644 --- a/code/game/g_itemLoad.cpp +++ b/code/game/g_itemLoad.cpp @@ -103,7 +103,7 @@ static void IT_Name(const char **holdBuf) return; } - + // Posto : hello, why not randomizing weapons and item drops ? if (!Q_stricmp(tokenStr,"ITM_NONE")) itemNum = ITM_NONE; else if (!Q_stricmp(tokenStr,"ITM_STUN_BATON_PICKUP")) @@ -206,7 +206,7 @@ static void IT_Name(const char **holdBuf) { itemNum = ITM_BATTERY_PICKUP; } - // Posto : TODO + // Posto : hey, I was already here else if (!Q_stricmp(tokenStr,"ITM_SEEKER_PICKUP")) itemNum = ITM_SEEKER_PICKUP; else if (!Q_stricmp(tokenStr,"ITM_SHIELD_PICKUP")) @@ -684,12 +684,15 @@ static void IT_ParseParms(const char *buffer) } - -void IT_LoadItemParms (void) +// Posto : wait what ? items.dat don't exist in the 'release' version of the game. How can it know which items are which then ? +void IT_LoadItemParms (void) { char *buffer; int len; + // This function is called at every map load, meaning we can shuffle the content using our seed ! + // But ! I think we should keep items 'types' together (ammo roll for an other kind of ammo, weapon for a weapon etc...) IF it cause problem. + // If changing what kind of item it is doesn't provoke any kind of problem, I don't see why we shouldn't do a general shuffle len = gi.FS_ReadFile("ext_data/items.dat",(void **) &buffer); IT_ParseParms(buffer); diff --git a/code/game/g_items.h b/code/game/g_items.h index 57c8d3fe..df1b786f 100644 --- a/code/game/g_items.h +++ b/code/game/g_items.h @@ -6,7 +6,7 @@ // Items enums typedef enum { -ITM_NONE, +ITM_NONE, // 0 ITM_SABER_PICKUP, ITM_BRYAR_PISTOL_PICKUP, @@ -20,7 +20,7 @@ ITM_ROCKET_LAUNCHER_PICKUP, ITM_THERMAL_DET_PICKUP, ITM_TRIP_MINE_PICKUP, ITM_DET_PACK_PICKUP, -ITM_STUN_BATON_PICKUP, +ITM_STUN_BATON_PICKUP, // 13 ITM_BOT_LASER_PICKUP, ITM_EMPLACED_GUN_PICKUP, @@ -30,7 +30,7 @@ ITM_ATST_MAIN_PICKUP, ITM_ATST_SIDE_PICKUP, ITM_TIE_FIGHTER_PICKUP, ITM_RAPID_FIRE_CONC_PICKUP, -ITM_BLASTER_PISTOL_PICKUP, +ITM_BLASTER_PISTOL_PICKUP, // 22 ITM_AMMO_FORCE_PICKUP, ITM_AMMO_BLASTER_PICKUP, @@ -40,7 +40,7 @@ ITM_AMMO_ROCKETS_PICKUP, ITM_AMMO_EMPLACED_PICKUP, ITM_AMMO_THERMAL_PICKUP, ITM_AMMO_TRIPMINE_PICKUP, -ITM_AMMO_DETPACK_PICKUP, +ITM_AMMO_DETPACK_PICKUP, // 31 ITM_FORCE_HEAL_PICKUP, ITM_FORCE_LEVITATION_PICKUP, @@ -50,7 +50,7 @@ ITM_FORCE_PULL_PICKUP, ITM_FORCE_TELEPATHY_PICKUP, ITM_FORCE_GRIP_PICKUP, ITM_FORCE_LIGHTNING_PICKUP, -ITM_FORCE_SABERTHROW_PICKUP, +ITM_FORCE_SABERTHROW_PICKUP, // 40 ITM_BATTERY_PICKUP, ITM_SEEKER_PICKUP, @@ -59,15 +59,15 @@ ITM_BACTA_PICKUP, ITM_DATAPAD_PICKUP, ITM_BINOCULARS_PICKUP, ITM_SENTRY_GUN_PICKUP, -ITM_LA_GOGGLES_PICKUP, +ITM_LA_GOGGLES_PICKUP, // 48 ITM_MEDPAK_PICKUP, ITM_SHIELD_SM_PICKUP, ITM_SHIELD_LRG_PICKUP, ITM_GOODIE_KEY_PICKUP, -ITM_SECURITY_KEY_PICKUP, +ITM_SECURITY_KEY_PICKUP, // 53 -ITM_NUM_ITEMS +ITM_NUM_ITEMS // 54 }; // Inventory item enums diff --git a/code/game/g_misc_model.cpp b/code/game/g_misc_model.cpp index 43171bd0..2bf96d3b 100644 --- a/code/game/g_misc_model.cpp +++ b/code/game/g_misc_model.cpp @@ -8,6 +8,10 @@ extern cvar_t *g_spskill; +// Randomizer / Posto : funcitons +extern int GetRandomizedWeapon(); +extern int GetRandomizedAmmo(); + // // Helper functions // @@ -414,6 +418,8 @@ void SP_misc_model_gun_rack( gentity_t *ent ) { for ( int i = 0; i < ct; i++ ) { + // Posto : I might be hated for this, but randomizing weapons here should be the best + itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 2, ( i - 1 ) * 9 + crandom() * 2, ofz[i] ); } } @@ -504,6 +510,7 @@ void SP_misc_model_ammo_rack( gentity_t *ent ) gi.linkentity( ent ); } +// Posto : let me edit a bit, just to test // AMMO RACK!! void spawn_rack_goods( gentity_t *ent ) { @@ -589,6 +596,8 @@ void spawn_rack_goods( gentity_t *ent ) { for ( int i = 0; i < ct; i++ ) { + // Posto : I might be hated for this, but randomizing ammos here should be the best + itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 0.5f, (i-1)* 8, 7.0f ); } } @@ -627,6 +636,8 @@ void spawn_rack_goods( gentity_t *ent ) // the gun so we don't put the pack on the same spot..so pick either the left or right side pos = ( random() > .5 ) ? -1 : 1; + // Posto : Randomize the weapon here + it = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); GunRackAddItem( it, ent->s.origin, ent->s.angles, crandom() * 2, ( random() * 6 + 4 ) * pos, v_off ); } } @@ -645,6 +656,7 @@ void spawn_rack_goods( gentity_t *ent ) pos *= -1; } + // Posto : we should leave health as is, it would make the game too hard without any garanted health GunRackAddItem( health, ent->s.origin, ent->s.angles, crandom() * 0.5f, ( random() * 4 + 4 ) * pos, 24 ); } diff --git a/code/game/g_weaponLoad.cpp b/code/game/g_weaponLoad.cpp index 5faa59bb..890fea6e 100644 --- a/code/game/g_weaponLoad.cpp +++ b/code/game/g_weaponLoad.cpp @@ -142,6 +142,13 @@ void WPN_AltChargeFrc(const char **holdBuf); void WPN_StopFrc(const char **holdBuf); void WPN_SelectFrc(const char **holdBuf); //#endif // _IMMERSION +//#ifdef _RANDOMIZER +// Posto : Get randomized weapons and ammo in the map +int GetRandomizedAmmo(); +int GetRandomizedWeapon(); +//#endif _RANDOMIZER + + typedef struct { @@ -1322,6 +1329,8 @@ void WP_LoadWeaponParms (void) char *buffer; int len; + // Posto : this function is called at every map load, meaning we can shuffle the content using our seed ! + // Also, we can reshuffle the content of wepaon/ammo rack on g_misc_model to have even more len = gi.FS_ReadFile("ext_data/weapons.dat",(void **) &buffer); // initialise the data area @@ -1330,4 +1339,70 @@ void WP_LoadWeaponParms (void) WP_ParseParms(buffer); gi.FS_FreeFile( buffer ); //let go of the buffer +} + +// Posto : Functions called when getting a new kind of ammo / weapon (exemple : g_misc_model for ammo racks) +int GetRandomizedAmmo() +{ + // 8 kind of ammo, and we skip "none" and "force" + int rng = rand() % 8 + 2; + while (rng == 6) rng = rand() % 8 + 2; // In case we get a 6 (ammo_emplaced), reroll + + switch (rng) + { + case 2: + return AMMO_BLASTER; + case 3: + return AMMO_POWERCELL; + case 4: + return AMMO_METAL_BOLTS; + case 5: + return AMMO_ROCKETS; + case 7: + return AMMO_THERMAL; + case 8: + return AMMO_TRIPMINE; + case 9: + return AMMO_DETPACK; + default: // Secours + return AMMO_BLASTER; + } +} + +int GetRandomizedWeapon() +{ + // 13 kind of weapons, and we skip "none", and explosives maybe (?) + int rng = rand() % 13 + 1; + + switch (rng) + { + case 1: + return WP_SABER; + case 2: + return WP_BRYAR_PISTOL; + case 3: + return WP_BLASTER; + case 4: + return WP_DISRUPTOR; + case 5: + return WP_BOWCASTER; + case 6: + return WP_REPEATER; + case 7: + return WP_DEMP2; + case 8: + return WP_FLECHETTE; + case 9: + return WP_ROCKET_LAUNCHER; + case 10: + return WP_THERMAL; // Something wrong is happening, they can't be 'used' when picked up + case 11: + return WP_TRIP_MINE; // Something wrong is happening, they can't be 'used' when picked up + case 12: + return WP_DET_PACK; // Something wrong is happening, they can't be 'used' when picked up + case 13: + return WP_STUN_BATON; + default: // Secours + return WP_BLASTER; + } } \ No newline at end of file From 9ca2ce8c9a9ffac42439763d86ec28b200b6e4d7 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Thu, 17 Oct 2024 18:57:07 +0100 Subject: [PATCH 13/62] Prevent crash while copying seed string --- code/cgame/cg_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 50199348..a6111de4 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -1997,7 +1997,7 @@ Ghoul2 Insert End //Copy the value in hashString into cg_setSeed for use later //I can't believe there's no better way to do this - for (int i = 0; i < 9; i++) { + for (int i = 0; i < hashString.size(); i++) { cg_setSeed.string[i] = hashString.at(i); } } From df9dacdeb7252dc26f4a7e0d7d20cae7a3555d66 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Thu, 17 Oct 2024 19:48:14 +0100 Subject: [PATCH 14/62] Run seed regeneration on new game start --- code/cgame/cg_main.cpp | 29 ----------------------------- code/ui/ui_main.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index a6111de4..104f11f4 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -24,8 +24,6 @@ extern void CG_RegisterNPCEffects( team_t team ); extern qboolean G_ParseAnimFileSet( const char *filename, const char *animCFG, int *animFileIndex ); extern void CG_DrawDataPadInventorySelect( void ); -using namespace std::chrono; - void CG_Init( int serverCommandSequence ); qboolean CG_ConsoleCommand( void ); void CG_Shutdown( void ); @@ -1975,33 +1973,6 @@ Ghoul2 Insert End CG_RegisterCvars(); - //Reinitialise randomizer seed value if we're not using setSeed - if (cg_useSetSeed.value != 1) - { - //Get System Epoch Time - auto duration = system_clock::now().time_since_epoch(); - - //Convert duration to milliseconds - long milliseconds - = chrono::duration_cast( - duration) - .count(); - - //Hash the time to get a consistent length seed - hash hasher; - string s = to_string(milliseconds); - size_t hash = hasher(s); - - //Convert to string to make next conversion easier - string hashString = to_string(hash); - - //Copy the value in hashString into cg_setSeed for use later - //I can't believe there's no better way to do this - for (int i = 0; i < hashString.size(); i++) { - cg_setSeed.string[i] = hashString.at(i); - } - } - //moved from CG_GameStateReceived because it's loaded sooner now CG_InitLocalEntities(); diff --git a/code/ui/ui_main.cpp b/code/ui/ui_main.cpp index de4a2450..54433b54 100644 --- a/code/ui/ui_main.cpp +++ b/code/ui/ui_main.cpp @@ -19,9 +19,13 @@ USER INTERFACE MAIN #include "ui_shared.h" #include "../qcommon/stv_version.h" +#include +#include #define LISTBUFSIZE 10240 +using namespace std::chrono; + static struct { char listBuf[LISTBUFSIZE]; // The list of file names read in @@ -96,6 +100,8 @@ vmCvar_t ui_menuFiles; vmCvar_t ui_smallFont; vmCvar_t ui_bigFont; vmCvar_t ui_hudFiles; +vmCvar_t cg_setSeed; +vmCvar_t cg_useSetSeed; cvarTable_t cvarTable[] = { @@ -456,6 +462,32 @@ static qboolean UI_DeferMenuScript ( const char **args ) return qfalse; } +static void RegenerateSeed(void) { + //Reinitialise randomizer seed value if we're not using setSeed + if (cg_useSetSeed.value != 1) + { + //Get System Epoch Time + auto duration = system_clock::now().time_since_epoch(); + + //Convert duration to milliseconds + long milliseconds + = chrono::duration_cast( + duration) + .count(); + + //Hash the time to get a consistent length seed + hash hasher; + string s = to_string(milliseconds); + size_t hash = hasher(s); + + //Convert to string + string hashString = to_string(hash); + + //Update seed value + Cvar_Set("cg_setSeed", hashString.c_str()); + } +} + /* =============== UI_RunMenuScript @@ -619,6 +651,7 @@ extern void FS_Restart( void ); else if (Q_stricmp(name, "startgame") == 0) { Menus_CloseAll(); + RegenerateSeed(); if ( Cvar_VariableIntegerValue("com_demo") ) { #ifdef FINAL_BUILD From b530640c2df76b0b5f1d3454d92ee8cd1a549d84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 25 Oct 2024 12:03:59 +0200 Subject: [PATCH 15/62] Added all 'static' NPCs that are necessarry for the game to work smoothly (Imperial holding keys, NPC that need to be killed) --- code/base/assets_randomizer.pk3 | Bin 0 -> 15225 bytes code/base/jk2config.cfg | 2 +- code/game/NPC_spawn.cpp | 244 ++++++++++++++++++++++++++++---- code/game/g_weaponLoad.cpp | 14 +- 4 files changed, 227 insertions(+), 33 deletions(-) create mode 100644 code/base/assets_randomizer.pk3 diff --git a/code/base/assets_randomizer.pk3 b/code/base/assets_randomizer.pk3 new file mode 100644 index 0000000000000000000000000000000000000000..2799209b8b780fcec38e01efa791aa20359ad070 GIT binary patch literal 15225 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%0A$8Dfa9 zjvT8RS;K*UxKjS;4tqMx1Hj1O>@fr3MSNJ>l!07KupHp{KIFjta4v>VprcnK`t(7@ z5@xlnZDO8DHX%&_@G}}>6sNqmqWaI9-#(_VWotk=?iLeclIKqU64M=KYY=ljVGBLt z2{#wFf_Y@z+I7OHJ+esIpH5s#5WfF>|`$+)A`#GGj0wV_C5k z*ZsvoSWdiX9Fg-9ei)SX32G6uNX7!nI3GtIS5NnkLPkYmBnoJ;-77$+@XBkLQzd(r zR#<=&KM7v+(1k8(?3F(c*YI+FX`5=mN95+bc(TE)x<%H(!n=A|uC{hC0w1POe)XIx zS!(Ls!iE{e~T98^6J#@X;8HXTPe)ahLU`RnNbMXe6_(K4(-1@Z%^}Fa-^l$i&K6D|Lp1R zwB4z2?`BW9LdbMxD(8lB_fui!YJO)O$z{PThYTbULiE_vKXPZ^T`# zhVb_Bmwbs`r3~P*MjY5~KungZzdo9U8rwoQAW{`{cHtVscN0{vHuWr^4T|^=bA*t( zx%WS0Syjp+K7SwmAIP%Hc2x7cMi*oDdz@wFVQhiGe2%1uZ)vU(q9}Q17HRE-uDgDr zGbyiZ1E**Y6RKQ*Ng48z(MeK8n#yL-8LZ&(5VJtei;b<&Yk<49fsL+<*n6edhyurF z_fDfjGw*W+dK;VE=Bw)&Dypu{iPpictO=BR*KPT7t8=t{1~&t^CwNJym4NP3y}D@N zqk*n*ArNg!S6@NdCm`98HtnwAT{G;B^@Ajc&amXja? ziqj$x>f33L(Sqg>j%z&bh}fAnWD4vQe;2@t8lfCTyo~0zIK9A>lPO}SNl-ZfbX|r< z*4EHutA#BLm&%nAO*G_iW=EOB`U}M|8*G8ZUK9@yXo{PxuMtBlwc}1Ig2A;MlugFX(3h*MSvy!!TWwr}9+5Jy(M27;2GDBu(rd2}g$AUM8gyk%vb7UPPU~RDI>e1Zhg24zciJ9gG zE~*N_wf5SERvct|!Xp$AQ}SZ9?Y{_LE&YI4*vt%vf|VJ)$SqBn*HgFc{%OK+w!weo z7f=UHh2P&bd~2EHQh8Mp9bYe7Q%)TR*8em&+RX&ZKi{)x9?@Yug7woubw5 z2d1`x5-PIW$jVztqvhmze+fIaq?`^Pd!z)024i$xZ4us!=4Xr|)C6eQnGx6KgooxH zXJ!J%7gqGjK_Nm(eI<96-|l}NT-6MBa*VF~M*v^o3`k&0`K;cFpF^SyQuvd_gvip4 z{7JcMcNO~UD)|OzF3xyu=H?~ORU)@_MwsvNNrX;^UCI6AcxgW80^UHY^3_dg28-+l zzWQ1B$Q7jB6C3 zLtbE_WCoFpMfZY{H&&#mQYL76Efj;;+7pQzWK0LITDM|nVy9CoUKyX6dyCYpG@*Sv z?~Q5tb9eIS-Z4DfeV78NgK6LO2ykLVCW$6w<<2v=)>iEN?Ji&*&_b`^3P1@_M|?tG zQLW&^!yz`MS4nRFLBzc zLdv^k;ibYOl}8-eZ|73D3F&Yu{4NCZ~zv#X6&@r%M_VzxiNKl10H?{U$?mZQ{`zJ!#2$ zIkv=wUN?Bz%a%4}r;+3?M>`>ZoQmy|IBaJxIluGTSy?aNkBS^Fqo`{-fEDVtsvyev zX!a=;eLwX8k~IcYxeta@(3Ae#)Q|=O$MIi*dH)1_61eH-5PSPu#fN0oceVv zEiVPLmgByo2E?6C|J)HpQBV;Kl$V>OA7`S$K2LTT_lf)Vexpkjcl%)Yf(VI_$WIG0 zr4A79U4t#Ykf-LTTyig4`al*6+m4X~RHBQN4lT?TEGh`ADj2#O74;B%N=k=12XFXp zHu*DbW#CSqFv(GX&dMG14hti719<3ODp6q#9awuAZjI!AxGnxUIe$oH=1cnWU8S0W zzRb$2a3>und^gbRJ$T>MdXO3BjRBIBL%tHQc0n3DNg)8MIMNcEizv+Lwe3Ip?S#Cg zs4~52lD%7jy!+c5^EBtHyuqHZy>sLq);izpxBO5FeQpGyuF4O`i@khJ5y}jGo5e)Z zu1wt)v((B7C(e00eLu8`_2?b*L2b*%=9w>fo88e?l(C^awL|o`JgnTJI6FELcLR!c z_V7x*+IgSpR*FDTDljmQ{tEULmlS_12&j26=_z-r1Ukj_Tb!S>jW=DP~Gy_(U!tNcdZMi zPwk;!Nrbf2EoiLMlPRG?XC&z*{8oh~q*x6fGLrV*qXRUH0Y%gN<#|Dwt+a)vB`q`K z3N*OzPFc7r)G-vE!6rZR7|K4qE}!_GF?GZF!Yy>P+-nop4K?6v$)bR)>;Kx-BTxRx z4>}&ybmHtJrhDrRCBZ+Hcw@2{!!CpPBN=jfvViPVnvr%}MEd6PArn8dy3vBC$RfH; z-b25H9K_T{#`ofja}YJZg0~La74o9rr=6V7<*^*ZVJ1$y%@ov=MXQU}Hxm}(^B$wV zrw0g)bWMTZBG$q;)5|e!3=(JSatPI8=WN~KR9&P0{4J_=vF=_ib>e8k9_w=BRi&rD zX%VUfZgfKm`vl8>fT%cR^Y#@rxbw4YOvJ?Y4&mz4cCB-8_0=y1^*I!BdR01?7CE7R zF5)?4KW>1z!|RPs(F^+V=qqE`*mLI>8-Vh4cg2=+pZoXAw!}~+9S5hvgbX#rEu_Nx zvyf3)^nMs@FMo%-Ewpn&?(^s35-gk)o^S`VrGE79evh==GB*$G>EHun2}2^?UImD> zHSo>p;|Oy%hlDc&kZWld2OQis5^{o|q3FWn1jSikKY`^yoy0Z+nuf*+(hl$q&#Yth zo~5me!Jyuv`Dw8gb2%A+rbOaLG7UeaDCg|a6)Yo z!PaBKu6j~3SLUQ-eDdBVMkmF z2B&$iq@GeHFt|)O!~kurHH6?f7IB>|Q69A_rnOcM=9<<5t6LXik=atd5*K3&M+r*- zs_H1RZonMoZ01aEe6NZI=8;LN9WMISlS8f692&c0x4?}6VC!F-TWimy&;WYx9Y2PHEmh5!?rQ%EWz8}q_NG)7 z0AMYFr~~28S1u#+G*}5%*)B-kY7p%M_VDj1`kyqm6_;){YiyD*^)$|mO||D4QM2J# zt*X}jY5Vzt{Y%gct+(#-x+gET;XA=)9F0_95vc44WuUO~l=mgCk9&H}sct@JsOz;m z?4HW6=+G%jc(`ns;4bWe6v)L?L3QaGC)48tFHL@Q3FGJmcsk+R1J+;5 z!ghj|O9##v;by0H6P8<%Mg0a3&iU)ZwLgJrZ3J8+&k#7sB91PoqL0R&%U6B#Y9YJ0 zBxUftCO4<7P^_avb3O~v$g|`k66UNcy!VWL1L&xO5eLxx@KMNEDu@OqjN60SO@cso zui>J&sS)7~1V2sv?F^{5z5RF74!8L?ICjCdWfR!cR~clO6R#Yy7H-+qd zYtT#79UwzGP*59y3aP2tQ0X5a%IpFzS&L@EV*<7$*z6tpOW-0C*t{Src5}-yb64!kK{DFRiKv5m6CEt1qPAYgiMrA)>q# zDqB(cUQU=G8xNsv7P2&Yr{l<>5qyWP6e2lytr#x~WNmjQk+z;DeMT>1vE#C5)n61X zP-QD5?q+=PXM&Dh>_xs66|;E%$9dQ9h;O9+!qCcxkfY9rSMMDGM@^08ISTV5R*vRWr!W!S6ko%@P4wVFt?pviI`(^-w~`?U3{ud_Oi zlv~|wfLA{a&-%$r0Rr&>{QqT1N&YKUitu0hFIfr&K=7XhAOHryvYJvu@xnTwB6Ot| zImRX+#+Q~m@jv|^)Bmsh>3^I4hY#Vu=b!2SJB|9khY+3e0rLDa{cmL=*8abS{NI@R ze-F|77k&LVi+>w Cfl^@r literal 0 HcmV?d00001 diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index 68a4e61f..8e55f3e6 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -186,7 +186,7 @@ seta cg_drawGun "1" seta cm_playerCurveClip "1" seta cg_crosshairForceHint "1" seta g_spskill "0" -seta cg_drawSpeed "0" +seta cg_drawSpeed "1" seta cg_gunAutoFirst "1" seta cg_saberAutoThird "0" seta g_subtitles "2" diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 32803912..5b48d1ce 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2788,12 +2788,12 @@ void SP_NPC_Droid_Protocol( gentity_t *self) // The Posto is for faster search so I know what I edited -const short tabSize = 20; +const short tabSize = 50; short tabLockedInNPC[tabSize] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; - //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - //-1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; short currentTabPosition = 0; char lastKnownMap[32] = "first_iteration"; @@ -2981,7 +2981,7 @@ void RandomizerDebugCommandCatcher(int page) //gi.Printf(S_COLOR_GREEN"Page number received : %d\n",page); // Just for information : the console is 30 lines long, - if (page <= 0 || page >= 5) // The help page, when we reach an undefined number. + if (page <= 0 || page >= 6) // The help page, when we reach an undefined number. { gi.Printf(S_COLOR_RED"Oops, it seems that you didn't provide a valid page number.\n"); gi.Printf(S_COLOR_RED"Welcome to the default page.\n"); @@ -2990,7 +2990,8 @@ void RandomizerDebugCommandCatcher(int page) gi.Printf(S_COLOR_WHITE"Page 2 : Currently generated NPCs on this map (%s).\n",level.mapname); gi.Printf(S_COLOR_WHITE"Page 3 : Rules for NPCs.\n"); gi.Printf(S_COLOR_WHITE"Page 4 : Rules for maps.\n"); - gi.Printf(S_COLOR_WHITE"Page 5+ : Todo\n"); + gi.Printf(S_COLOR_WHITE"Page 5 : Rules for weapons / ammo\n"); + gi.Printf(S_COLOR_WHITE"Page 6 : Todo\n"); return; // So that we won't go to the switch bellow } switch (page) @@ -3010,15 +3011,15 @@ void RandomizerDebugCommandCatcher(int page) gi.Printf(S_COLOR_CYAN"NPC number %d is : %s.\n", i + 1, GetNPCNames(tabLockedInNPC[i])); } } - else gi.Printf(S_COLOR_CYAN"ALL NPC can spawn (except the ones banned do to them being unstable / broken).\n"); + else gi.Printf(S_COLOR_CYAN"ALL NPC can spawn (except the ones banned due to them being unstable / broken / run-killers (Desann)).\n"); break; case 3: // Which NPC are forced no matter which map (Jan for exemple, not having her breaks the first map and yavin_swamp cutscene as far as I know). Update this if needed - gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now thta's how it is.\n"); + gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now that's how it is.\n"); gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will ALWAYS spawn as themselves, no matter which map you are on :\n"); gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, ATST, Mark1, Mark2 (Chicken robot), R2D2, R5D2 and SeekerDrones.\n"); gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will NEVER randomly spawn, no matter which map you are on :\n"); - gi.Printf(S_COLOR_CYAN""); + gi.Printf(S_COLOR_CYAN"Tavion, Desann, ATST, Chicken Robot (Mark2) and bugged monsters (Glider...)\n"); break; case 4: // Map specific locked NPCs (thinking about the officer in assembly to open the first door)(maybe other NPCs can do it, but idk). Update this if needed. gi.Printf(S_COLOR_MAGENTA"Some spawn on specific maps are forced, so that we don't softlock the game.\n"); @@ -3026,6 +3027,13 @@ void RandomizerDebugCommandCatcher(int page) gi.Printf(S_COLOR_MAGENTA"Here is the list of maps that have specific NPC locked :\n"); gi.Printf(S_COLOR_CYAN"Todo.\n"); break; + case 5: // + gi.Printf(S_COLOR_MAGENTA"Here are the general rules for how weapons will work :\n"); + gi.Printf(S_COLOR_CYAN"Weapons are replaced by other weapons (a E-11 blaster can become a bowcaster).\n"); + gi.Printf(S_COLOR_CYAN"Ammo are replaced with another king of ammo. Explosives are considered ammo, so you can find them here and not in weapons slots.\n"); + gi.Printf(S_COLOR_CYAN"Items on the ground (like the bowcaster on artus_mines or bactas in general) remain unchanged.\n"); + gi.Printf(S_COLOR_CYAN"Health pack on weapon/ammo rack are constants too.\n"); + break; default: return; } @@ -3051,7 +3059,6 @@ void SP_NPC_Spawn_Random(gentity_t* self) } // Let's suppose we find a way to have any kind of NPC, we can authorize anything in our big array, so that we don't have to change "much" of the code. - if (tabSize == 50) { for (int i = 0; i < tabSize; i++) tabLockedInNPC[i] = i; @@ -3086,9 +3093,10 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_MonMothma(self); PopulateNPCTab(rng); break; - case 5: - SP_NPC_Tavion(self); - PopulateNPCTab(rng); + case 5: // Desann and Tavion are too hard to handle, I will keep them out for now + //SP_NPC_Tavion(self); + //PopulateNPCTab(rng); + SP_NPC_Spawn_Random(self); break; case 6: // Il a une IA au moins ? SP_NPC_Reelo(self); @@ -3098,9 +3106,10 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_Galak(self); PopulateNPCTab(rng); break; - case 8: - SP_NPC_Desann(self); - PopulateNPCTab(rng); + case 8: // Desann and Tavion are too hard to handle, I will keep them out for now + //SP_NPC_Desann(self); + //PopulateNPCTab(rng); + SP_NPC_Spawn_Random(self); break; case 9: // Il a une IA au moins ? SP_NPC_Bartender(self); @@ -3270,9 +3279,10 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_Droid_R2D2(self); PopulateNPCTab(rng); break; - case 48: - SP_NPC_Droid_R5D2(self); - PopulateNPCTab(rng); + case 48: // Spawning this droid on kejim_base is making the game crash ???? + //SP_NPC_Droid_R5D2(self); + //PopulateNPCTab(rng); + SP_NPC_Spawn_Random(self); break; case 49: SP_NPC_Droid_Protocol(self); @@ -3284,6 +3294,62 @@ void SP_NPC_Spawn_Random(gentity_t* self) break; } } + +void SpawnValidKeyholder(gentity_t* self) // Presumably an humanoid, since droids crashes the game. +{ + // X being the number of valid NPC that can hold a key + int rng = rand() % 5; + + // In the meantime, here is Kyle + //SP_NPC_Kyle(self); + + switch (rng) + { + case 0: + break; + default: + break; + } +} + +bool CheckForceSpawn(gentity_t* self, char whatWeCompare[], char whoToSpawn[]) // Used in maps when we will spawn something +{ + // It's either NPC_targetname or targetname, check for both and return when done. + if (self->NPC_targetname) // Check if NULL + { + if (strncmp(self->NPC_targetname, whatWeCompare, strlen(self->NPC_targetname)) == 0) // Got it, we have to spawn this entity + { + // Temporary : just spawn the 'normal' NPC + if (strcmp(whoToSpawn, "Rebel") == 0) SP_NPC_Rebel(self); + if (strcmp(whoToSpawn, "Imperial") == 0) SP_NPC_Imperial(self); + if (strcmp(whoToSpawn, "Rodian") == 0) SP_NPC_Rodian(self); + if (strcmp(whoToSpawn, "Stormtrooper") == 0) SP_NPC_Stormtrooper(self); + if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); + if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); + if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); + + return true; // True, we forcefully spawned something + } + } + if (self->targetname) // Check if NULL + { + if (strncmp(self->targetname, whatWeCompare, strlen(self->targetname)) == 0) // Got it, we have to spawn this entity + { + // Temporary : just spawn the 'normal' NPC + if (strcmp(whoToSpawn, "Rebel") == 0) SP_NPC_Rebel(self); + if (strcmp(whoToSpawn, "Imperial") == 0) SP_NPC_Imperial(self); + if (strcmp(whoToSpawn, "Rodian") == 0) SP_NPC_Rodian(self); + if (strcmp(whoToSpawn, "Stormtrooper") == 0) SP_NPC_Stormtrooper(self); + if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); + if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); + if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); + + return true; // True, we forcefully spawned something + } + } + return false; // False, it's not a forced spawn +} + void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle { CheckIfMapChanged(); @@ -3297,11 +3363,6 @@ void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan { CheckIfMapChanged(); - //if (lastKnownMap == "kejim_post") // That's not C - if (strcmp(lastKnownMap,"kejim_post") == 0 ) - { - int proofOfConcept = 777; - } SP_NPC_Jan(self); } void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke @@ -3357,11 +3418,24 @@ void SP_NPC_Prisoner_Random(gentity_t* self) // Prisoners should spawn as themse void SP_NPC_Rebel_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The rebel being shot on has to be constant + { + if (CheckForceSpawn(self, "rebel_target", "Rebel")) return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_Stormtrooper_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The stormtooper shooting the rebel has to be constant + { + if (CheckForceSpawn(self, "shooter", "Stormtrooper")) return; + } + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + { + SP_NPC_Stormtrooper(self); + return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_StormtrooperOfficer_Random(gentity_t* self) @@ -3379,19 +3453,41 @@ void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaugh CheckIfMapChanged(); SP_NPC_Ugnaught(self); } -void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? +void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two TS thrower at the end of the mission + { + CheckForceSpawn(self, "t198", "Gran"); + return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_Rodian_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_streets") == 0) + { + if (CheckForceSpawn(self, "bouncer_main1", "Rodian")) return; // The two Rodians that will get our weapons + if (CheckForceSpawn(self, "bouncer_main2", "Rodian")) return; // The two Rodians that will get our weapons + } + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (CheckForceSpawn(self, "reelo_thug", "Rodian")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "end_thug", "Rodian")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + } SP_NPC_Spawn_Random(self); } void SP_NPC_Weequay_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (CheckForceSpawn(self, "reelo_thug", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "end_thug", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + } SP_NPC_Spawn_Random(self); } void SP_NPC_Trandoshan_Random(gentity_t* self) @@ -3407,11 +3503,93 @@ void SP_NPC_SwampTrooper_Random(gentity_t* self) void SP_NPC_Imperial_Random(gentity_t* self) { CheckIfMapChanged(); + // Won't make a special function, he is an unique case + if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick has to be constant + { + if (self->behaviorSet[0]) // Check for NULL + { + if (strcmp(self->behaviorSet[0], "cairn_assembly/silent_stand") == 0) + { + SP_NPC_Imperial(self); + return; + } + } + } + if (strcmp(lastKnownMap, "kejim_base") == 0) + { + if (CheckForceSpawn(self, "explosion_victims", "Imperial")) return; // The dead Imperial holding a security key + if (CheckForceSpawn(self, "ambush_io", "Imperial")) return; // The first Imperial + if (self->behaviorSet[0] && (strcmp(self->behaviorSet[0], "common/crouchshoot") == 0)) + { + // ONLY the Imperial hiding in the corner, not the one standing (they both have the same target name) + CheckForceSpawn(self, "corridor_enemies", "Imperial"); + return; + } + } + if (strcmp(lastKnownMap, "artus_detention") == 0) + { + if (CheckForceSpawn(self, "warden", "Imperial")) return; // The warden that we have hostage + } + if (strcmp(lastKnownMap, "doom_detention") == 0) + { + if (CheckForceSpawn(self, "jailer", "Imperial")) return; // The jailer of Jan + if (self->message && strcmp(self->message, "ele_key2") == 0) // The Imperial holding a key in the big room + { + CheckForceSpawn(self, "squad7", "Imperial"); + return; + } + } + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + { + SP_NPC_Imperial(self); + return; + } + if (strcmp(lastKnownMap, "artus_topside") == 0) + { + if (self->message && strcmp(self->message, "shield_key") == 0) // The Imperial holding a key in the ATST room + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } + } + if (strcmp(lastKnownMap, "bespin_streets") == 0) + { + if (self->message && strcmp(self->message, "exit_key") == 0) // The Imperial holding a key at the end of the level + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } + } + if (strcmp(lastKnownMap, "bespin_platform") == 0) + { + if (self->message && strcmp(self->message, "control_room") == 0) // The Imperial holding a key at the end of the level + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } + } + if (strcmp(lastKnownMap, "doom_comm") == 0) + { + if (self->message && strcmp(self->message, "hey_presto") == 0) // The Imperial holding a key to access the 'call room' + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } + } SP_NPC_Spawn_Random(self); } void SP_NPC_ImpWorker_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + { + SP_NPC_ImpWorker(self); + return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_BespinCop_Random(gentity_t* self) @@ -3422,11 +3600,27 @@ void SP_NPC_BespinCop_Random(gentity_t* self) void SP_NPC_Reborn_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two reborn at the end of the mission + { + CheckForceSpawn(self, "t179", "Reborn"); + CheckForceSpawn(self, "t199", "Reborn"); + return; + } + if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The two reborn we have to kill in oprder to spawn the ATST at the end + { + CheckForceSpawn(self, "squad18", "Reborn"); + return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_ShadowTrooper_Random(gentity_t* self) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, too many undefined behaviours + { + SP_NPC_ShadowTrooper(self); + return; + } SP_NPC_Spawn_Random(self); } void SP_NPC_Monster_Murjj_Random(gentity_t* self) // Who is that ? diff --git a/code/game/g_weaponLoad.cpp b/code/game/g_weaponLoad.cpp index 890fea6e..31fcb828 100644 --- a/code/game/g_weaponLoad.cpp +++ b/code/game/g_weaponLoad.cpp @@ -1371,13 +1371,13 @@ int GetRandomizedAmmo() int GetRandomizedWeapon() { - // 13 kind of weapons, and we skip "none", and explosives maybe (?) - int rng = rand() % 13 + 1; + // 13 kind of weapons, and we skip "none", the lightsaber, explosives and the stun baton + int rng = rand() % 8 + 2; switch (rng) { - case 1: - return WP_SABER; + case 1: + return WP_SABER; // Impossible for now, it's rather buggy, let's just get it naturally at yavin_trial case 2: return WP_BRYAR_PISTOL; case 3: @@ -1395,11 +1395,11 @@ int GetRandomizedWeapon() case 9: return WP_ROCKET_LAUNCHER; case 10: - return WP_THERMAL; // Something wrong is happening, they can't be 'used' when picked up + return WP_THERMAL; // Something wrong is happening, they have no ammo when picked up case 11: - return WP_TRIP_MINE; // Something wrong is happening, they can't be 'used' when picked up + return WP_TRIP_MINE; // Something wrong is happening, they have no ammo when picked up case 12: - return WP_DET_PACK; // Something wrong is happening, they can't be 'used' when picked up + return WP_DET_PACK; // Something wrong is happening, they have no ammo when picked up case 13: return WP_STUN_BATON; default: // Secours From 97f9b60ead0b465629d6d2b9beee095653963023 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Fri, 25 Oct 2024 20:15:24 +0100 Subject: [PATCH 16/62] move seed reset into g_main.cpp --- code/game/g_main.cpp | 36 ++++++++++++++++++++++++++++++++++++ code/ui/ui_main.cpp | 34 +--------------------------------- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index 5651c762..d6ef680a 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -15,6 +15,11 @@ #include "objectives.h" #include "../cgame/cg_local.h" // yeah I know this is naughty, but we're shipping soon... +#include +#include + +using namespace std::chrono; + extern CNavigator navigator; static int navCalcPathTime = 0; int eventClearTime = 0; @@ -567,6 +572,33 @@ void G_InitCvars( void ) { g_iscensored = gi.cvar( "ui_iscensored", "0", CVAR_ARCHIVE|CVAR_ROM|CVAR_INIT|CVAR_CHEAT|CVAR_NORESTART ); } +void RegenerateSeed(void) { + //Reinitialise randomizer seed value if we're not using setSeed + if (gi.Cvar_VariableIntegerValue("cg_useSetSeed") != 1) + { + //Get System Epoch Time + auto duration = system_clock::now().time_since_epoch(); + + //Convert duration to milliseconds + long milliseconds + = chrono::duration_cast( + duration) + .count(); + + //Hash the time to get a consistent length seed + hash hasher; + string s = to_string(milliseconds); + size_t hash = hasher(s); + + //Convert to string + string hashString = to_string(hash); + + //Update seed value + gi.cvar_set("cg_setSeed", hashString.c_str()); + //Cvar_Set("cg_setSeed", hashString.c_str()); + } +} + /* ============ InitGame @@ -587,6 +619,10 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons { int i; + //Reset randomiser seed on new load of kejim_post + if (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) { + RegenerateSeed(); + } giMapChecksum = checkSum; g_eSavedGameJustLoaded = eSavedGameJustLoaded; g_qbLoadTransition = qbLoadTransition; diff --git a/code/ui/ui_main.cpp b/code/ui/ui_main.cpp index 54433b54..409a1d0c 100644 --- a/code/ui/ui_main.cpp +++ b/code/ui/ui_main.cpp @@ -19,13 +19,9 @@ USER INTERFACE MAIN #include "ui_shared.h" #include "../qcommon/stv_version.h" -#include -#include #define LISTBUFSIZE 10240 -using namespace std::chrono; - static struct { char listBuf[LISTBUFSIZE]; // The list of file names read in @@ -100,8 +96,6 @@ vmCvar_t ui_menuFiles; vmCvar_t ui_smallFont; vmCvar_t ui_bigFont; vmCvar_t ui_hudFiles; -vmCvar_t cg_setSeed; -vmCvar_t cg_useSetSeed; cvarTable_t cvarTable[] = { @@ -462,32 +456,6 @@ static qboolean UI_DeferMenuScript ( const char **args ) return qfalse; } -static void RegenerateSeed(void) { - //Reinitialise randomizer seed value if we're not using setSeed - if (cg_useSetSeed.value != 1) - { - //Get System Epoch Time - auto duration = system_clock::now().time_since_epoch(); - - //Convert duration to milliseconds - long milliseconds - = chrono::duration_cast( - duration) - .count(); - - //Hash the time to get a consistent length seed - hash hasher; - string s = to_string(milliseconds); - size_t hash = hasher(s); - - //Convert to string - string hashString = to_string(hash); - - //Update seed value - Cvar_Set("cg_setSeed", hashString.c_str()); - } -} - /* =============== UI_RunMenuScript @@ -651,7 +619,7 @@ extern void FS_Restart( void ); else if (Q_stricmp(name, "startgame") == 0) { Menus_CloseAll(); - RegenerateSeed(); + if ( Cvar_VariableIntegerValue("com_demo") ) { #ifdef FINAL_BUILD From 2e0a49ac123a22ebe882dc0992b0bdaa5de43d5e Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sat, 2 Nov 2024 19:46:43 +0000 Subject: [PATCH 17/62] Prevent allies from attacking enemies with ignore_enemies flag on --- code/game/NPC_behavior.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/NPC_behavior.cpp b/code/game/NPC_behavior.cpp index c90a25c5..07d5ad88 100644 --- a/code/game/NPC_behavior.cpp +++ b/code/game/NPC_behavior.cpp @@ -540,7 +540,7 @@ void NPC_BSFollowLeader (void) return; } - if ( !NPC->enemy ) + if ( !NPC->enemy && !NPCInfo->scriptFlags&SVF_IGNORE_ENEMIES) //Only look for an enemy if ignore enemies is not set {//no enemy, find one NPC_CheckEnemy( NPCInfo->confusionTimeenemy ) @@ -588,7 +588,7 @@ void NPC_BSFollowLeader (void) } } } - else + else if (!NPCInfo->scriptFlags & SVF_IGNORE_ENEMIES) { if ( NPC->enemy->health <= 0 || (NPC->enemy->flags&FL_NOTARGET) ) { From 8a12a666a821662ff1704cc29c7c54d763db1300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Mon, 4 Nov 2024 10:56:33 +0100 Subject: [PATCH 18/62] Added a condition to check is the Randomizer is enabled. This way, this version of the game can be added to SpeedOutcast to have a single executable for both the base game and the Randomizer. --- Posto-Stuff-ReadmePLZ.txt | 24 +- code/base/assets_speedoutcast.pk3.old | Bin 0 -> 14545 bytes code/base/jk2config.cfg | 3 +- code/cgame/cg_draw.cpp | 29 +- code/cgame/cg_local.h | 1 + code/cgame/cg_main.cpp | 4 +- code/game/NPC_spawn.cpp | 603 +++++++++++++++++--------- code/game/bg_misc.cpp | 16 +- code/game/g_client.cpp | 20 +- code/game/g_itemLoad.cpp | 2 +- code/game/g_items.cpp | 1 + code/game/g_misc_model.cpp | 16 +- 12 files changed, 490 insertions(+), 229 deletions(-) create mode 100644 code/base/assets_speedoutcast.pk3.old diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt index 5e918a4a..76ac2744 100644 --- a/Posto-Stuff-ReadmePLZ.txt +++ b/Posto-Stuff-ReadmePLZ.txt @@ -45,21 +45,17 @@ Here is what I could grab as the max number of different NPC on a map in Vanilla Needed NPC per map : -- None (but need confirmation): kejim_post, kejim_base, artus_mine, yavin_trial, cairn_bay, cairn_reactor, doom_comm, doom_shield, yavin_swamp, yavin_canyon, -- artus_detention : the officer with the loooong sequence -- artus_topside : the prisoners, Desann spawn naturally -- valley : maybe ????? -- yavin_temple : maybe Luke or C3P0 ????? need to confirm -- ns_street : Bartender, but it's already forced. Also the entity that takes away the briar blaster need to be 'humanoid' or the game will crash, need to check that. +- None (but need confirmation): kejim_post, artus_mine, yavin_trial, cairn_bay, cairn_reactor, doom_comm, doom_shield, yavin_swamp, yavin_canyon, +- kejim_base : the corpse that hold the security key to open the mouse droid pad +- artus_detention : the officer/guard with the long sequence +- ns_street : The entity that takes away the briar blaster need to be 'humanoid' / able to hold the blaster. So locking the rodians it is. - ns_hideout : Lando and Reelo, but both are already forced -- ns_starpas : Lando and maybe Reelo -- bespin_undercity : the guy who opens the door, and R5D2 are forced (need to confirm) -- bespin_streets : R5D2 already forced -- bespin_platform : Tavion is forced -- cairn_assembly : The officer that open the door, maybe something else -- cairn_dock1 : maybe forcing everything here, because random NPC behavior are strange, also Luke and Desann -- doom_detention : the officer that open the door and Jan -- yavin_courtyard : maybe locking everything here (the trooper shoioting the rebel, the jedis are maybe necessary to unlock the scene) +- ns_starpas : The two waves of ennemies, it seems that if a neutral spawn, it's kill isn't counted (not sure) +- bespin_undercity : the entity (don't know his name) that opens the door when using force mind trick +- cairn_assembly : The officer that open the door with mind trick +- cairn_dock1 : maybe forcing everything here, because random NPC behavior are strange (they start focusing you). This one I can just filter the mapo entirely +- doom_detention : the officer that open the door to Jan cell +- yavin_courtyard : the trooper shooting the rebel and the rebel being shot CURRENT SITUATION : I locked the number of max unique NPC to 10 for now. diff --git a/code/base/assets_speedoutcast.pk3.old b/code/base/assets_speedoutcast.pk3.old new file mode 100644 index 0000000000000000000000000000000000000000..630a3aa57c57b876dab92eb1d968086c6ca6ddd6 GIT binary patch literal 14545 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 ZzZ?Fa<-sBT^FpBi2KGPmV$T0m{{sO@uqOZj literal 0 HcmV?d00001 diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index 8e55f3e6..fb217e7a 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -69,7 +69,7 @@ bind MOUSE5 "+force_lightning" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta cg_setSeed "7898612456" +seta cg_setSeed "2852812379" seta cg_useSetSeed "0" seta cg_drawSeed "1" seta r_weatherScale "1" @@ -308,3 +308,4 @@ seta in_midiport "1" seta in_midi "0" seta sp_language "1" seta com_maxfps "125" +seta cg_enableRandomizer "1" diff --git a/code/cgame/cg_draw.cpp b/code/cgame/cg_draw.cpp index b46c8109..0ac765c1 100644 --- a/code/cgame/cg_draw.cpp +++ b/code/cgame/cg_draw.cpp @@ -2342,10 +2342,20 @@ CG_DrawSeed =============== */ static float CG_DrawSeed(float y) { - const char* seed_string = va("Seed: %s", cg_setSeed.string); - const int width = cgi_R_Font_StrLenPixels(seed_string, cgs.media.qhFontMedium, 1.0f); - cgi_R_Font_DrawString(635 - width, y + 2, seed_string, colorTable[CT_LTGOLD1], cgs.media.qhFontMedium, -1, 1.0f); - return y + BIGCHAR_HEIGHT + 10; + if (cg_enableRandomizer.integer) + { + const char* seed_string = va("Seed: %s", cg_setSeed.string); + const int width = cgi_R_Font_StrLenPixels(seed_string, cgs.media.qhFontMedium, 1.0f); + cgi_R_Font_DrawString(635 - width, y + 2, seed_string, colorTable[CT_LTGOLD1], cgs.media.qhFontMedium, -1, 1.0f); + return y + BIGCHAR_HEIGHT + 10; + } + else + { + const char* seed_string = va("Randomizer Disabled"); + const int width = cgi_R_Font_StrLenPixels(seed_string, cgs.media.qhFontMedium, 1.0f); + cgi_R_Font_DrawString(635 - width, y + 2, seed_string, colorTable[CT_DKORANGE], cgs.media.qhFontMedium, -1, 1.0f); + return y + BIGCHAR_HEIGHT + 10; + } } static float jumpHelperGetRangeExtendingLength(const int force_jump_level) { @@ -2704,7 +2714,16 @@ static void CG_Draw2D( void ) { CG_DrawOverbounceInfo(); } - if ( cg_drawSeed.integer ) + + // Encapsulate every code related to the Randomizer behind this kind of condition. + /*if (cg_enableRandomizer.integer) + { + if (cg_drawSeed.integer) + { + CG_DrawSeed(y); + } + }*/ + if (cg_drawSeed.integer) { CG_DrawSeed(y); } diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index d2755fe3..6d1e880e 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -694,6 +694,7 @@ extern vmCvar_t cg_strafeHelperColorSpeedB; extern vmCvar_t cg_strafeHelperColorSpeedA; //Additions for Randomizer +extern vmCvar_t cg_enableRandomizer; extern vmCvar_t cg_drawSeed; extern vmCvar_t cg_setSeed; diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index 104f11f4..9d37de6a 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -391,6 +391,7 @@ vmCvar_t cg_strafeHelperColorSpeedB; vmCvar_t cg_strafeHelperColorSpeedA; // Additions for Randomizer +vmCvar_t cg_enableRandomizer; vmCvar_t cg_drawSeed; vmCvar_t cg_useSetSeed; vmCvar_t cg_setSeed; @@ -580,8 +581,9 @@ Ghoul2 Insert End { &cg_strafeHelperColorSpeedA, "cg_strafeHelperColorSpeedA", "0.9", CVAR_ARCHIVE }, // Additions for Randomizer + { &cg_enableRandomizer, "cg_enableRandomizer", "0", CVAR_ARCHIVE }, // By default, it's disabled { &cg_drawSeed, "cg_drawSeed", "0", CVAR_ARCHIVE }, - { &cg_useSetSeed, "cg_useSetSeed", "", CVAR_ARCHIVE }, + { &cg_useSetSeed, "cg_useSetSeed", "0", CVAR_ARCHIVE }, { &cg_setSeed, "cg_setSeed", "", CVAR_ARCHIVE } }; diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 5b48d1ce..b9da83fe 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -59,6 +59,8 @@ extern void NPC_GalakMech_Init( gentity_t *ent ); extern void NPC_Protocol_Precache( void ); extern int WP_SetSaberModel( gclient_t *client, class_t npcClass ); +// Randomizer +extern vmCvar_t cg_enableRandomizer; extern vmCvar_t cg_useSetSeed; extern vmCvar_t cg_setSeed; @@ -2786,8 +2788,8 @@ void SP_NPC_Droid_Protocol( gentity_t *self) NPC_Protocol_Precache(); } - -// The Posto is for faster search so I know what I edited +// Randomizer +// The 'Posto' is for faster search so I know what I edited const short tabSize = 50; short tabLockedInNPC[tabSize] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -2981,6 +2983,7 @@ void RandomizerDebugCommandCatcher(int page) //gi.Printf(S_COLOR_GREEN"Page number received : %d\n",page); // Just for information : the console is 30 lines long, + // Even if the Randomizer is disabled, randomizer_debug (maybe renamed to randomizer_info) will still print this page. if (page <= 0 || page >= 6) // The help page, when we reach an undefined number. { gi.Printf(S_COLOR_RED"Oops, it seems that you didn't provide a valid page number.\n"); @@ -3350,391 +3353,589 @@ bool CheckForceSpawn(gentity_t* self, char whatWeCompare[], char whoToSpawn[]) / return false; // False, it's not a forced spawn } +// If the Randomizer is disabled, just a bit of process time is added at every check, but at least it should be comptable with the standard SpeedOutcast void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle { - CheckIfMapChanged(); - SP_NPC_Kyle(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Kyle(self); + } + else SP_NPC_Kyle(self); } void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando { - CheckIfMapChanged(); - SP_NPC_Lando(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Lando(self); + } + else SP_NPC_Lando(self); } void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan { - CheckIfMapChanged(); - SP_NPC_Jan(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Jan(self); + } + else SP_NPC_Jan(self); } void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke { - CheckIfMapChanged(); - SP_NPC_Luke(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Luke(self); + } + else SP_NPC_Luke(self); } void SP_NPC_MonMothma_Random(gentity_t* self) // MonMothma should always spawn as MonMothma { - CheckIfMapChanged(); - SP_NPC_MonMothma(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_MonMothma(self); + } + else SP_NPC_MonMothma(self); } void SP_NPC_Tavion_Random(gentity_t* self) // Tavion should always spawn as Tavion { - CheckIfMapChanged(); - SP_NPC_Tavion(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Tavion(self); + } + else SP_NPC_Tavion(self); } void SP_NPC_Reelo_Random(gentity_t* self) // Reelo should always spawn as Reelo { - CheckIfMapChanged(); - SP_NPC_Reelo(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Reelo(self); + } + else SP_NPC_Reelo(self); } void SP_NPC_Galak_Random(gentity_t* self) // Galak should always spawn as Galak { - CheckIfMapChanged(); - SP_NPC_Galak(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Galak(self); + } + else SP_NPC_Galak(self); } void SP_NPC_Desann_Random(gentity_t* self) // Desann should always spawn as Desann { - CheckIfMapChanged(); - SP_NPC_Desann(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Desann(self); + } + else SP_NPC_Desann(self); } void SP_NPC_Bartender_Random(gentity_t* self) // Bartender should always spawn as Bartender { - CheckIfMapChanged(); - SP_NPC_Bartender(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Bartender(self); + } + else SP_NPC_Bartender(self); } void SP_NPC_MorganKatarn_Random(gentity_t* self) // Morgarn should always spawn as Morgarn { - CheckIfMapChanged(); - SP_NPC_MorganKatarn(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_MorganKatarn(self); + } + else SP_NPC_MorganKatarn(self); } void SP_NPC_Jedi_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Jedi(self); } void SP_NPC_Prisoner_Random(gentity_t* self) // Prisoners should spawn as themselves { - CheckIfMapChanged(); - SP_NPC_Prisoner(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Prisoner(self); + } + else SP_NPC_Prisoner(self); } void SP_NPC_Rebel_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The rebel being shot on has to be constant + if (cg_enableRandomizer.integer) { - if (CheckForceSpawn(self, "rebel_target", "Rebel")) return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The rebel being shot on has to be constant + { + if (CheckForceSpawn(self, "rebel_target", "Rebel")) return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Rebel(self); } void SP_NPC_Stormtrooper_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The stormtooper shooting the rebel has to be constant - { - if (CheckForceSpawn(self, "shooter", "Stormtrooper")) return; - } - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + if (cg_enableRandomizer.integer) { - SP_NPC_Stormtrooper(self); - return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The stormtooper shooting the rebel has to be constant + { + if (CheckForceSpawn(self, "shooter", "Stormtrooper")) return; + } + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + { + SP_NPC_Stormtrooper(self); + return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Stormtrooper(self); } void SP_NPC_StormtrooperOfficer_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_StormtrooperOfficer(self); } void SP_NPC_Tie_Pilot_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Tie_Pilot(self); } void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaught { - CheckIfMapChanged(); - SP_NPC_Ugnaught(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Ugnaught(self); + } + else SP_NPC_Ugnaught(self); } void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two TS thrower at the end of the mission + if (cg_enableRandomizer.integer) { - CheckForceSpawn(self, "t198", "Gran"); - return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two TS thrower at the end of the mission + { + CheckForceSpawn(self, "t198", "Gran"); + return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Gran(self); } void SP_NPC_Rodian_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "ns_streets") == 0) - { - if (CheckForceSpawn(self, "bouncer_main1", "Rodian")) return; // The two Rodians that will get our weapons - if (CheckForceSpawn(self, "bouncer_main2", "Rodian")) return; // The two Rodians that will get our weapons - } - if (strcmp(lastKnownMap, "ns_starpad") == 0) + if (cg_enableRandomizer.integer) { - if (CheckForceSpawn(self, "reelo_thug", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "end_thug", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_streets") == 0) + { + if (CheckForceSpawn(self, "bouncer_main1", "Rodian")) return; // The two Rodians that will get our weapons + if (CheckForceSpawn(self, "bouncer_main2", "Rodian")) return; // The two Rodians that will get our weapons + } + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (CheckForceSpawn(self, "reelo_thug", "Rodian")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "end_thug", "Rodian")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Rodian(self); } void SP_NPC_Weequay_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "ns_starpad") == 0) + if (cg_enableRandomizer.integer) { - if (CheckForceSpawn(self, "reelo_thug", "Weequay")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "end_thug", "Weequay")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (CheckForceSpawn(self, "reelo_thug", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "end_thug", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Weequay(self); } void SP_NPC_Trandoshan_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Trandoshan(self); } void SP_NPC_SwampTrooper_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_SwampTrooper(self); } void SP_NPC_Imperial_Random(gentity_t* self) { - CheckIfMapChanged(); - // Won't make a special function, he is an unique case - if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick has to be constant + if (cg_enableRandomizer.integer) { - if (self->behaviorSet[0]) // Check for NULL + CheckIfMapChanged(); + // Won't make a special function, he is an unique case + if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick has to be constant { - if (strcmp(self->behaviorSet[0], "cairn_assembly/silent_stand") == 0) + if (self->behaviorSet[0]) // Check for NULL { - SP_NPC_Imperial(self); + if (strcmp(self->behaviorSet[0], "cairn_assembly/silent_stand") == 0) + { + SP_NPC_Imperial(self); + return; + } + } + } + if (strcmp(lastKnownMap, "kejim_base") == 0) + { + if (CheckForceSpawn(self, "explosion_victims", "Imperial")) return; // The dead Imperial holding a security key + if (CheckForceSpawn(self, "ambush_io", "Imperial")) return; // The first Imperial + if (self->behaviorSet[0] && (strcmp(self->behaviorSet[0], "common/crouchshoot") == 0)) + { + // ONLY the Imperial hiding in the corner, not the one standing (they both have the same target name) + CheckForceSpawn(self, "corridor_enemies", "Imperial"); return; } } - } - if (strcmp(lastKnownMap, "kejim_base") == 0) - { - if (CheckForceSpawn(self, "explosion_victims", "Imperial")) return; // The dead Imperial holding a security key - if (CheckForceSpawn(self, "ambush_io", "Imperial")) return; // The first Imperial - if (self->behaviorSet[0] && (strcmp(self->behaviorSet[0], "common/crouchshoot") == 0)) + if (strcmp(lastKnownMap, "artus_detention") == 0) { - // ONLY the Imperial hiding in the corner, not the one standing (they both have the same target name) - CheckForceSpawn(self, "corridor_enemies", "Imperial"); - return; + if (CheckForceSpawn(self, "warden", "Imperial")) return; // The warden that we have hostage } - } - if (strcmp(lastKnownMap, "artus_detention") == 0) - { - if (CheckForceSpawn(self, "warden", "Imperial")) return; // The warden that we have hostage - } - if (strcmp(lastKnownMap, "doom_detention") == 0) - { - if (CheckForceSpawn(self, "jailer", "Imperial")) return; // The jailer of Jan - if (self->message && strcmp(self->message, "ele_key2") == 0) // The Imperial holding a key in the big room + if (strcmp(lastKnownMap, "doom_detention") == 0) { - CheckForceSpawn(self, "squad7", "Imperial"); - return; + if (CheckForceSpawn(self, "jailer", "Imperial")) return; // The jailer of Jan + if (self->message && strcmp(self->message, "ele_key2") == 0) // The Imperial holding a key in the big room + { + CheckForceSpawn(self, "squad7", "Imperial"); + return; + } } - } - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm - { - SP_NPC_Imperial(self); - return; - } - if (strcmp(lastKnownMap, "artus_topside") == 0) - { - if (self->message && strcmp(self->message, "shield_key") == 0) // The Imperial holding a key in the ATST room + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm { - // This guy doesn't have a target, so we just spawn him SP_NPC_Imperial(self); return; } - } - if (strcmp(lastKnownMap, "bespin_streets") == 0) - { - if (self->message && strcmp(self->message, "exit_key") == 0) // The Imperial holding a key at the end of the level + if (strcmp(lastKnownMap, "artus_topside") == 0) { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; + if (self->message && strcmp(self->message, "shield_key") == 0) // The Imperial holding a key in the ATST room + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } } - } - if (strcmp(lastKnownMap, "bespin_platform") == 0) - { - if (self->message && strcmp(self->message, "control_room") == 0) // The Imperial holding a key at the end of the level + if (strcmp(lastKnownMap, "bespin_streets") == 0) { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; + if (self->message && strcmp(self->message, "exit_key") == 0) // The Imperial holding a key at the end of the level + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } } - } - if (strcmp(lastKnownMap, "doom_comm") == 0) - { - if (self->message && strcmp(self->message, "hey_presto") == 0) // The Imperial holding a key to access the 'call room' + if (strcmp(lastKnownMap, "bespin_platform") == 0) { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; + if (self->message && strcmp(self->message, "control_room") == 0) // The Imperial holding a key at the end of the level + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } + } + if (strcmp(lastKnownMap, "doom_comm") == 0) + { + if (self->message && strcmp(self->message, "hey_presto") == 0) // The Imperial holding a key to access the 'call room' + { + // This guy doesn't have a target, so we just spawn him + SP_NPC_Imperial(self); + return; + } } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Imperial(self); } void SP_NPC_ImpWorker_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + if (cg_enableRandomizer.integer) { - SP_NPC_ImpWorker(self); - return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm + { + SP_NPC_ImpWorker(self); + return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_ImpWorker(self); } void SP_NPC_BespinCop_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_BespinCop(self); } void SP_NPC_Reborn_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two reborn at the end of the mission - { - CheckForceSpawn(self, "t179", "Reborn"); - CheckForceSpawn(self, "t199", "Reborn"); - return; - } - if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The two reborn we have to kill in oprder to spawn the ATST at the end + if (cg_enableRandomizer.integer) { - CheckForceSpawn(self, "squad18", "Reborn"); - return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two reborn at the end of the mission + { + CheckForceSpawn(self, "t179", "Reborn"); + CheckForceSpawn(self, "t199", "Reborn"); + return; + } + if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The two reborn we have to kill in oprder to spawn the ATST at the end + { + CheckForceSpawn(self, "squad18", "Reborn"); + return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_Reborn(self); } void SP_NPC_ShadowTrooper_Random(gentity_t* self) { - CheckIfMapChanged(); - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, too many undefined behaviours + if (cg_enableRandomizer.integer) { - SP_NPC_ShadowTrooper(self); - return; + CheckIfMapChanged(); + if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, too many undefined behaviours + { + SP_NPC_ShadowTrooper(self); + return; + } + SP_NPC_Spawn_Random(self); } - SP_NPC_Spawn_Random(self); + else SP_NPC_ShadowTrooper(self); } void SP_NPC_Monster_Murjj_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Murjj(self); } void SP_NPC_Monster_Swamp_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Swamp(self); } void SP_NPC_Monster_Howler_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Howler(self); } void SP_NPC_Monster_Claw_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Claw(self); } void SP_NPC_Monster_Glider_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Glider(self); } void SP_NPC_Monster_Flier2_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Flier2(self); } void SP_NPC_Monster_Lizard_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Lizard(self); } void SP_NPC_Monster_Fish_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Monster_Fish(self); } void SP_NPC_MineMonster_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_MineMonster(self); } void SP_NPC_Droid_Interrogator_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Interrogator(self); } void SP_NPC_Droid_Probe_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Probe(self); } void SP_NPC_Droid_Mark1_Random(gentity_t* self) // Chicken robot, make then static and not in the random pool (they are big). Wait, two chicken robot entities ? { - CheckIfMapChanged(); - //SP_NPC_Spawn_Random(self); - SP_NPC_Droid_Mark1(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_Mark1(self); + } + else SP_NPC_Droid_Mark1(self); } void SP_NPC_Droid_Mark2_Random(gentity_t* self) // Chicken robot, make then static and not in the random pool (they are big). Wait, two chicken robot entities ? { - CheckIfMapChanged(); - //SP_NPC_Spawn_Random(self); - SP_NPC_Droid_Mark2(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_Mark2(self); + } + else SP_NPC_Droid_Mark2(self); } void SP_NPC_Droid_ATST_Random(gentity_t* self) // Since they are buggy, let's keep the one existing intact. { - CheckIfMapChanged(); - //SP_NPC_Spawn_Random(self); - SP_NPC_Droid_ATST(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_ATST(self); + } + else SP_NPC_Droid_ATST(self); } void SP_NPC_Droid_Seeker_Random(gentity_t* self) // Seekers should always be seekers, at least in speedruns { - CheckIfMapChanged(); - SP_NPC_Droid_Seeker(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_Seeker(self); + } + else SP_NPC_Droid_Seeker(self); } void SP_NPC_Droid_Remote_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Remote(self); } void SP_NPC_Droid_Sentry_Random(gentity_t* self) // Who is that ? { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Sentry(self); } void SP_NPC_Droid_Gonk_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Gonk(self); } void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse { - CheckIfMapChanged(); - SP_NPC_Droid_Mouse(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Spawn_Random(self); + } + else SP_NPC_Droid_Mouse(self); } void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self { - CheckIfMapChanged(); - SP_NPC_Droid_R2D2(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_R2D2(self); + } + else SP_NPC_Droid_R2D2(self); } void SP_NPC_Droid_R5D2_Random(gentity_t* self) // R5D2 should spawn as self { - CheckIfMapChanged(); - SP_NPC_Droid_R5D2(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_R5D2(self); + } + else SP_NPC_Droid_R5D2(self); } void SP_NPC_Droid_Protocol_Random(gentity_t* self) { - CheckIfMapChanged(); - SP_NPC_Droid_Protocol(self); + if (cg_enableRandomizer.integer) + { + CheckIfMapChanged(); + SP_NPC_Droid_Protocol(self); + } + else SP_NPC_Droid_Protocol(self); } diff --git a/code/game/bg_misc.cpp b/code/game/bg_misc.cpp index 0012b295..f919a8b4 100644 --- a/code/game/bg_misc.cpp +++ b/code/game/bg_misc.cpp @@ -183,10 +183,14 @@ FindItemForWeapon =============== */ gitem_t *FindItemForWeapon( weapon_t weapon ) { + // Posto : this is called during map load, to know what kind of weapon is on the ground (ex : cairn_dock1). It's in this .cpp that I have to randomize things ?????!!!!! + int i; for ( i = 1 ; i < bg_numItems ; i++ ) { if ( bg_itemlist[i].giType == IT_WEAPON && bg_itemlist[i].giTag == weapon ) { + //int rng = rand() % 5 + 2; + //return &bg_itemlist[rng]; return &bg_itemlist[i]; } } @@ -198,12 +202,16 @@ gitem_t *FindItemForWeapon( weapon_t weapon ) { //---------------------------------------------- gitem_t *FindItemForInventory( int inv ) { + // Posto : when called in kejim_post, only bacta and binocular is returned; while on cairndock_1, a lot of things is returned (sentry, seeker). + // It MUST be here that I randomize things, but how ? int i; gitem_t *it; // Now just check for any other kind of item. for ( i = 1 ; i < bg_numItems ; i++ ) { + //int rng = i + rand() % 2; + //it = &bg_itemlist[rng]; it = &bg_itemlist[i]; if ( it->giType == IT_HOLDABLE ) @@ -233,6 +241,8 @@ gitem_t *FindItemForAmmo( ammo_t ammo ) { if ( bg_itemlist[i].giType == IT_AMMO && bg_itemlist[i].giTag == ammo ) { + //int rng = rand() % 4 + 1; + //return &bg_itemlist[rng]; return &bg_itemlist[i]; } } @@ -251,8 +261,12 @@ gitem_t *FindItem( const char *className ) { int i; for ( i = 1 ; i < bg_numItems ; i++ ) { - if ( !Q_stricmp( bg_itemlist[i].classname, className ) ) + if (!Q_stricmp(bg_itemlist[i].classname, className)) + { + //int rng = rand() % 4 + 1; + //return &bg_itemlist[rng]; return &bg_itemlist[i]; + } } return NULL; diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index 4193a72e..208fda63 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -16,6 +16,7 @@ extern vmCvar_t cg_thirdPersonAlpha; // Posto / Randomizer : for the first weapon (It might roll a stun baton again, would be pretty funny) extern int GetRandomizedWeapon(); +extern vmCvar_t cg_enableRandomizer; // g_client.c -- client functions that don't happen every frame @@ -1522,7 +1523,10 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded else { G_LoadAnimFileSet( ent, "kyle" ); + //G_LoadAnimFileSet(ent, "jan"); + // Posto : maybe it's here that we can 'randomize' how we look like ? Not being Kyle could be funny G_SetSkin( ent, "kyle", NULL ); + //G_SetSkin(ent, "jan", NULL); } } else @@ -1601,8 +1605,14 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded // give default weapons client->ps.stats[STAT_WEAPONS] = ( 1 << WP_NONE ); // Posto : Hey, we can randomize our first weapon ! - //client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BRYAR_PISTOL ); //these are precached in g_items, ClearRegisteredItems() - client->ps.stats[STAT_WEAPONS] |= (1 << (weapon_t)(GetRandomizedWeapon())); + if (cg_enableRandomizer.integer) + { + client->ps.stats[STAT_WEAPONS] |= (1 << (weapon_t)(GetRandomizedWeapon())); + } + else + { + client->ps.stats[STAT_WEAPONS] |= (1 << WP_BRYAR_PISTOL); //these are precached in g_items, ClearRegisteredItems() + } client->ps.inventory[INV_ELECTROBINOCULARS] = 1; // always give the bryar pistol, but we have to give EITHER the saber or the stun baton..never both @@ -1650,6 +1660,7 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded G_KillBox( ent ); gi.linkentity (ent); // force the base weapon up + // Posto : here's why we are loading kejim_base with the Bryal Pistol, might want to work on that client->ps.weapon = WP_BRYAR_PISTOL; client->ps.weaponstate = WEAPON_READY; } @@ -1683,7 +1694,9 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded if (eSavedGameJustLoaded == eNO) { ent->weaponModel = -1; + // Posto : maybe it's here that we can 'randomize' how we look like ? Not being Kyle could be funny G_SetG2PlayerModel( ent, "kyle", NULL, NULL, NULL ); + //G_SetG2PlayerModel(ent, "jan", NULL, NULL, NULL); } else { @@ -1695,7 +1708,10 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded else { G_LoadAnimFileSet( ent, "kyle" ); + //G_LoadAnimFileSet(ent, "jan"); + // Posto : maybe it's here that we can 'randomize' how we look like ? Not being Kyle could be funny G_SetSkin( ent, "kyle", NULL ); + //G_SetSkin(ent, "jan", NULL); } } /* diff --git a/code/game/g_itemLoad.cpp b/code/game/g_itemLoad.cpp index c61415b1..da009576 100644 --- a/code/game/g_itemLoad.cpp +++ b/code/game/g_itemLoad.cpp @@ -103,7 +103,7 @@ static void IT_Name(const char **holdBuf) return; } - // Posto : hello, why not randomizing weapons and item drops ? + // Posto : hello, why not randomizing weapons and item drops ? Posto again : that's true brother, need to work on that if (!Q_stricmp(tokenStr,"ITM_NONE")) itemNum = ITM_NONE; else if (!Q_stricmp(tokenStr,"ITM_STUN_BATON_PICKUP")) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 3469a55c..4639c4e9 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -777,6 +777,7 @@ free fall from their spawn points #ifndef FINAL_BUILD extern int delayedShutDown; #endif +// Posto / Randomizer : might want to check when this is called, to randomize even items on the ground (shield and bacta are going here) void FinishSpawningItem( gentity_t *ent ) { trace_t tr; vec3_t dest; diff --git a/code/game/g_misc_model.cpp b/code/game/g_misc_model.cpp index 2bf96d3b..88c5f2f5 100644 --- a/code/game/g_misc_model.cpp +++ b/code/game/g_misc_model.cpp @@ -11,6 +11,7 @@ extern cvar_t *g_spskill; // Randomizer / Posto : funcitons extern int GetRandomizedWeapon(); extern int GetRandomizedAmmo(); +extern vmCvar_t cg_enableRandomizer; // // Helper functions @@ -419,7 +420,10 @@ void SP_misc_model_gun_rack( gentity_t *ent ) for ( int i = 0; i < ct; i++ ) { // Posto : I might be hated for this, but randomizing weapons here should be the best - itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + if (cg_enableRandomizer.integer) + { + itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 2, ( i - 1 ) * 9 + crandom() * 2, ofz[i] ); } } @@ -597,7 +601,10 @@ void spawn_rack_goods( gentity_t *ent ) for ( int i = 0; i < ct; i++ ) { // Posto : I might be hated for this, but randomizing ammos here should be the best - itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); + if (cg_enableRandomizer.integer) + { + itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); + } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 0.5f, (i-1)* 8, 7.0f ); } } @@ -637,7 +644,10 @@ void spawn_rack_goods( gentity_t *ent ) pos = ( random() > .5 ) ? -1 : 1; // Posto : Randomize the weapon here - it = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + if (cg_enableRandomizer.integer) + { + it = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + } GunRackAddItem( it, ent->s.origin, ent->s.angles, crandom() * 2, ( random() * 6 + 4 ) * pos, v_off ); } } From be6016ea3672dbe427fa373752fe0a7dfc7f3223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Tue, 5 Nov 2024 11:26:34 +0100 Subject: [PATCH 19/62] Tests to get an "all items" randomizer. --- code/base/jk2config.cfg | 478 +++++++++++----------- code/cgame/cg_draw.cpp | 2 +- code/game/g_combat.cpp | 8 + code/game/g_items.cpp | 100 +++++ code/game/g_misc_model.cpp | 6 +- code/speedrun/speedrun_timer_includes.cpp | 17 + 6 files changed, 368 insertions(+), 243 deletions(-) diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg index fb217e7a..9f6c0f9a 100644 --- a/code/base/jk2config.cfg +++ b/code/base/jk2config.cfg @@ -69,243 +69,243 @@ bind MOUSE5 "+force_lightning" bind DOWNARROW "+back" bind LEFTARROW "+left" bind RIGHTARROW "+right" -seta cg_setSeed "2852812379" -seta cg_useSetSeed "0" -seta cg_drawSeed "1" -seta r_weatherScale "1" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" -seta d_slowmodeath "0" -seta ui_iscensored "0" -seta g_speedFactorLanding "1.0" -seta g_saber_color "yellow" -seta g_saberAutoAim "1" -seta g_saberAnimSpeed "1" -seta g_saberMoveSpeed "1" -seta g_saberRealisticCombat "0" -seta g_saberAutoBlocking "1" -seta g_dismemberProbabilities "1" -seta g_dismemberment "3" -seta cg_strafeHelperColorSpeedA "0.9" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperCenter "1" -seta cg_drawStrafeHelper "0" -seta cg_speedColorA "0.1" -seta cg_speedColorB "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorR "1.0" -seta cg_speedY "75" -seta cg_speedX "0" -seta cg_speedScale "0.9" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperY "0" -seta cg_jumpHelperX "0" -seta cg_drawJumpHelper "0" -seta cg_drawOverbounceInfo "0" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSecrets "0" -seta cg_reliableAnimSounds "1" -seta cg_missionInfoCentered "1" -seta cg_bobroll "0.002" -seta cg_bobpitch "0.002" -seta cg_bobup "0.005" -seta cg_runroll "0.005" -seta cg_runpitch "0.002" -seta cg_simpleItems "0" -seta cg_crosshairY "0" -seta cg_crosshairX "0" -seta cg_crosshairSize "24" -seta cg_crosshairIdentifyTarget "1" -seta cg_dynamicCrosshair "1" -seta cg_drawAmmoWarning "1" -seta cg_drawSnapshot "0" -seta cg_drawServerFPS "1" -seta cg_drawFPS "1" -seta cg_drawTimer "1" -seta cg_drawStatus "1" -seta cg_draw2D "1" -seta cg_stereoSeparation "0.4" -seta cg_drawGun "1" -seta cm_playerCurveClip "1" -seta cg_crosshairForceHint "1" -seta g_spskill "0" -seta cg_drawSpeed "1" -seta cg_gunAutoFirst "1" -seta cg_saberAutoThird "0" -seta g_subtitles "2" -seta ui_r_glCustom "4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_bigFont "0.4" -seta ui_smallFont "0.25" -seta ui_menuFiles "ui/menus.txt" -seta cg_marks "1" -seta cg_drawCrosshair "1" -seta ff_delay "40" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta use_ff "1" -seta s_soundpoolmegs "25" -seta s_UseOpenAL "0" -seta s_mp3overhead "31756" -seta s_language "francais" -seta s_mixPreStep "0.05" -seta s_mixahead "0.2" -seta s_allowDynamicMusic "1" -seta s_khz "22" -seta s_separation "0.5" -seta s_musicvolume "0.015625" -seta s_volumeVoice "0.039062" -seta s_volume "0.039062" -seta vid_ypos "0" -seta vid_xpos "0" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta r_modelpoolmegs "20" -seta cg_shadows "0" -seta r_showtriscolor "0" -seta r_primitives "0" -seta r_facePlaneCull "1" -seta r_gamma "1.359375" -seta r_swapInterval "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_finish "0" -seta r_dlightBacks "1" -seta r_dynamiclight "1" -seta r_drawSun "0" -seta r_fastsky "0" -seta r_ignoreGLErrors "1" -seta r_lodscale "10" -seta r_flares "1" -seta r_lodbias "0" -seta r_lodCurveError "250" -seta r_intensity "1" -seta r_ignoreFastPath "1" -seta r_subdivisions "4" -seta r_vertexLight "0" -seta r_simpleMipMaps "1" -seta r_customaspect "1" -seta r_customheight "1024" -seta r_customwidth "1600" -seta r_fullscreen "0" -seta r_mode "8" -seta r_ignorehwgamma "0" -seta r_overBrightBits "1" -seta r_depthbits "24" -seta r_stencilbits "8" -seta r_stereo "0" -seta r_colorbits "32" -seta r_texturebitslm "0" -seta r_texturebits "0" -seta r_detailtextures "1" -seta r_picmip "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_ext_texture_env_add "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_multitexture "1" -seta r_ext_gamma_control "1" -seta r_ext_preferred_tc_method "0" -seta r_ext_compress_lightmaps "0" -seta r_ext_compress_textures "1" -seta r_allowExtensions "1" -seta handicap "100" -seta sex "male" -seta snaps "20" -seta name "Kyle" -seta m_filter "0" -seta m_side "0.25" -seta m_forward "0.25" -seta m_yaw "0.022" -seta m_pitch "0.022" -seta cg_autoswitch "0" -seta cl_VideoQuality "0" -seta cl_ingameVideo "1" -seta cl_freelook "1" -seta cl_mouseAccel "0" -seta sensitivity "5" -seta cl_run "1" -seta cl_packetdup "1" -seta cl_maxpackets "30" -seta cl_anglespeedkey "1.5" -seta cl_pitchspeed "140" -seta cl_yawspeed "140" -seta panoNumShots "10" -seta conAlpha "1.6" -seta sv_timedCheckpointMaxZ "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinX "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeIL "0" -seta joy_ybutton "0" -seta joy_xbutton "1" -seta js_ffmult "3.0" -seta joy_threshold "0.15" -seta in_joyBallScale "0.02" -seta in_joystick "0" -seta in_mouse_raw "1" -seta in_mouse "-1" -seta in_mididevice "0" -seta in_midichannel "1" -seta in_midiport "1" -seta in_midi "0" -seta sp_language "1" -seta com_maxfps "125" seta cg_enableRandomizer "1" +seta com_maxfps "125" +seta sp_language "1" +seta in_midi "0" +seta in_midiport "1" +seta in_midichannel "1" +seta in_mididevice "0" +seta in_mouse "-1" +seta in_mouse_raw "1" +seta in_joystick "0" +seta in_joyBallScale "0.02" +seta joy_threshold "0.15" +seta js_ffmult "3.0" +seta joy_xbutton "1" +seta joy_ybutton "0" +seta sv_speedrunModeIL "0" +seta sv_speedrunModeCheckpoint "0" +seta sv_speedrunModeCheckpointSave "0" +seta sv_timedCheckpointMinX "0" +seta sv_timedCheckpointMinY "0" +seta sv_timedCheckpointMinZ "0" +seta sv_timedCheckpointMaxX "0" +seta sv_timedCheckpointMaxY "0" +seta sv_timedCheckpointMaxZ "0" +seta conAlpha "1.6" +seta panoNumShots "10" +seta cl_yawspeed "140" +seta cl_pitchspeed "140" +seta cl_anglespeedkey "1.5" +seta cl_maxpackets "30" +seta cl_packetdup "1" +seta cl_run "1" +seta sensitivity "5" +seta cl_mouseAccel "0" +seta cl_freelook "1" +seta cl_ingameVideo "1" +seta cl_VideoQuality "0" +seta cg_autoswitch "0" +seta m_pitch "0.022" +seta m_yaw "0.022" +seta m_forward "0.25" +seta m_side "0.25" +seta m_filter "0" +seta name "Kyle" +seta snaps "20" +seta sex "male" +seta handicap "100" +seta r_allowExtensions "1" +seta r_ext_compress_textures "1" +seta r_ext_compress_lightmaps "0" +seta r_ext_preferred_tc_method "0" +seta r_ext_gamma_control "1" +seta r_ext_multitexture "1" +seta r_ext_compiled_vertex_array "1" +seta r_ext_texture_env_add "1" +seta r_ext_texture_filter_anisotropic "1" +seta r_picmip "1" +seta r_detailtextures "1" +seta r_texturebits "0" +seta r_texturebitslm "0" +seta r_colorbits "32" +seta r_stereo "0" +seta r_stencilbits "8" +seta r_depthbits "24" +seta r_overBrightBits "1" +seta r_ignorehwgamma "0" +seta r_mode "8" +seta r_fullscreen "0" +seta r_customwidth "1600" +seta r_customheight "1024" +seta r_customaspect "1" +seta r_simpleMipMaps "1" +seta r_vertexLight "0" +seta r_subdivisions "4" +seta r_ignoreFastPath "1" +seta r_intensity "1" +seta r_lodCurveError "250" +seta r_lodbias "0" +seta r_flares "1" +seta r_lodscale "10" +seta r_ignoreGLErrors "1" +seta r_fastsky "0" +seta r_drawSun "0" +seta r_dynamiclight "1" +seta r_dlightBacks "1" +seta r_finish "0" +seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" +seta r_swapInterval "0" +seta r_gamma "1.359375" +seta r_facePlaneCull "1" +seta r_primitives "0" +seta r_showtriscolor "0" +seta cg_shadows "0" +seta r_modelpoolmegs "20" +seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" +seta vid_xpos "10" +seta vid_ypos "2" +seta s_volume "0.039062" +seta s_volumeVoice "0.039062" +seta s_musicvolume "0.015625" +seta s_separation "0.5" +seta s_khz "22" +seta s_allowDynamicMusic "1" +seta s_mixahead "0.2" +seta s_mixPreStep "0.05" +seta s_language "francais" +seta s_mp3overhead "31756" +seta s_UseOpenAL "0" +seta s_soundpoolmegs "25" +seta use_ff "1" +seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" +seta ff_delay "40" +seta cg_drawCrosshair "1" +seta cg_marks "1" +seta ui_menuFiles "ui/menus.txt" +seta ui_smallFont "0.25" +seta ui_bigFont "0.4" +seta cg_hudFiles "ui/jk2hud.txt" +seta ui_r_glCustom "4" +seta g_subtitles "2" +seta cg_saberAutoThird "0" +seta cg_gunAutoFirst "1" +seta cg_drawSpeed "1" +seta g_spskill "0" +seta cg_crosshairForceHint "1" +seta cm_playerCurveClip "1" +seta cg_drawGun "1" +seta cg_stereoSeparation "0.4" +seta cg_draw2D "1" +seta cg_drawStatus "1" +seta cg_drawTimer "1" +seta cg_drawFPS "1" +seta cg_drawServerFPS "1" +seta cg_drawSnapshot "0" +seta cg_drawAmmoWarning "1" +seta cg_dynamicCrosshair "1" +seta cg_crosshairIdentifyTarget "1" +seta cg_crosshairSize "24" +seta cg_crosshairX "0" +seta cg_crosshairY "0" +seta cg_simpleItems "0" +seta cg_runpitch "0.002" +seta cg_runroll "0.005" +seta cg_bobup "0.005" +seta cg_bobpitch "0.002" +seta cg_bobroll "0.002" +seta cg_missionInfoCentered "1" +seta cg_reliableAnimSounds "1" +seta cg_drawSecrets "0" +seta cg_drawSpeedrunTotalTimer "4" +seta cg_drawSpeedrunLevelTimer "1" +seta cg_drawOverbounceInfo "0" +seta cg_drawJumpHelper "0" +seta cg_jumpHelperX "0" +seta cg_jumpHelperY "0" +seta cg_jumpHelperWidth "300" +seta cg_jumpHelperHeight "20" +seta cg_jumpHelperHorizontal "1" +seta cg_jumpHelperMirror "1" +seta cg_jumpHelperAutoScale "0" +seta cg_jumpHelperCrouch "1" +seta cg_jumpHelperCurrentScale "0.5" +seta cg_jumpHelperColorBackgroundR "0.0" +seta cg_jumpHelperColorBackgroundG "0.0" +seta cg_jumpHelperColorBackgroundB "0.0" +seta cg_jumpHelperColorBackgroundA "0.2" +seta cg_jumpHelperColorCancelR "0.8" +seta cg_jumpHelperColorCancelG "0.8" +seta cg_jumpHelperColorCancelB "0.8" +seta cg_jumpHelperColorCancelA "0.75" +seta cg_jumpHelperColorCrouchR "0.0" +seta cg_jumpHelperColorCrouchG "1.0" +seta cg_jumpHelperColorCrouchB "1.0" +seta cg_jumpHelperColorCrouchA "0.75" +seta cg_jumpHelperColorCrouchExtendR "0.0" +seta cg_jumpHelperColorCrouchExtendG "0.333" +seta cg_jumpHelperColorCrouchExtendB "0.333" +seta cg_jumpHelperColorCrouchExtendA "0.375" +seta cg_jumpHelperColorCurrentR "1.0" +seta cg_jumpHelperColorCurrentG "1.0" +seta cg_jumpHelperColorCurrentB "1.0" +seta cg_jumpHelperColorCurrentA "0.75" +seta cg_jumpHelperColorExtendR "0.0" +seta cg_jumpHelperColorExtendG "0.5" +seta cg_jumpHelperColorExtendB "0.125" +seta cg_jumpHelperColorExtendA "0.375" +seta cg_jumpHelperColorOptimalR "0.0" +seta cg_jumpHelperColorOptimalG "1.0" +seta cg_jumpHelperColorOptimalB "0.25" +seta cg_jumpHelperColorOptimalA "0.75" +seta cg_speedScale "0.9" +seta cg_speedX "0" +seta cg_speedY "75" +seta cg_speedColorR "1.0" +seta cg_speedColorG "1.0" +seta cg_speedColorB "1.0" +seta cg_speedColorA "0.1" +seta cg_drawStrafeHelper "0" +seta cg_strafeHelperCenter "1" +seta cg_strafeHelperCenterMarker "1" +seta cg_strafeHelperHeight "20" +seta cg_strafeHelperScale "4" +seta cg_strafeHelperSpeedScale "0.9" +seta cg_strafeHelperSpeedX "0" +seta cg_strafeHelperSpeedY "0" +seta cg_strafeHelperY "50" +seta cg_strafeHelperColorAcceleratingR "0.0" +seta cg_strafeHelperColorAcceleratingG "0.5" +seta cg_strafeHelperColorAcceleratingB "0.125" +seta cg_strafeHelperColorAcceleratingA "0.375" +seta cg_strafeHelperColorOptimalR "0.0" +seta cg_strafeHelperColorOptimalG "1.0" +seta cg_strafeHelperColorOptimalB "0.25" +seta cg_strafeHelperColorOptimalA "0.75" +seta cg_strafeHelperColorCenterMarkerR "1.0" +seta cg_strafeHelperColorCenterMarkerG "1.0" +seta cg_strafeHelperColorCenterMarkerB "1.0" +seta cg_strafeHelperColorCenterMarkerA "0.75" +seta cg_strafeHelperColorSpeedR "1.0" +seta cg_strafeHelperColorSpeedG "1.0" +seta cg_strafeHelperColorSpeedB "1.0" +seta cg_strafeHelperColorSpeedA "0.9" +seta g_dismemberment "3" +seta g_dismemberProbabilities "1" +seta g_saberAutoBlocking "1" +seta g_saberRealisticCombat "0" +seta g_saberMoveSpeed "1" +seta g_saberAnimSpeed "1" +seta g_saberAutoAim "1" +seta g_saber_color "yellow" +seta g_speedFactorLanding "1.0" +seta ui_iscensored "0" +seta d_slowmodeath "0" +seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" +seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" +seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" +seta r_weatherScale "1" +seta cg_drawSeed "1" +seta cg_useSetSeed "0" +seta cg_setSeed "444444444" diff --git a/code/cgame/cg_draw.cpp b/code/cgame/cg_draw.cpp index 0ac765c1..27c4a91b 100644 --- a/code/cgame/cg_draw.cpp +++ b/code/cgame/cg_draw.cpp @@ -2351,7 +2351,7 @@ static float CG_DrawSeed(float y) { } else { - const char* seed_string = va("Randomizer Disabled"); + const char* seed_string = va("No Rand"); const int width = cgi_R_Font_StrLenPixels(seed_string, cgs.media.qhFontMedium, 1.0f); cgi_R_Font_DrawString(635 - width, y + 2, seed_string, colorTable[CT_DKORANGE], cgs.media.qhFontMedium, -1, 1.0f); return y + BIGCHAR_HEIGHT + 10; diff --git a/code/game/g_combat.cpp b/code/game/g_combat.cpp index 491f1be4..b5b35b33 100644 --- a/code/game/g_combat.cpp +++ b/code/game/g_combat.cpp @@ -3433,6 +3433,14 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int { if ( self->client->NPC_class == CLASS_DESANN && !strcmp(level.mapname, "yavin_final") ) { + // Randomizer + if (cg_enableRandomizer.integer) + { + gi.Printf(S_COLOR_RED "=========================\n"); + Com_Printf(S_COLOR_GREEN "Seed used: " S_COLOR_WHITE "%s\n",cg_setSeed.string); + gi.Printf(S_COLOR_RED "=========================\n"); + } + // final boss (desann) on final map is dead, speedrun is over cgi_SpeedrunRunFinished(); } diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 4639c4e9..a2a2af41 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -21,6 +21,9 @@ extern cvar_t *g_spskill; #define MAX_BACTA_HEAL_AMOUNT 25 +// Randomizer +extern vmCvar_t cg_enableRandomizer; + /* Items are any object that a player can touch to gain some effect. @@ -793,6 +796,103 @@ void FinishSpawningItem( gentity_t *ent ) { } } + // Randomizer : after getting the item from bg_itemlist, we can finally randomize it here, because every items goes into this function and not only "gun rack" + gitem_t* itemNew; + if (cg_enableRandomizer.integer) + { + // For tests prupose only + int rng = rand() % 54; + itemNew = bg_itemlist + rng; + while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 1)) // No saber, no baton, no strange items + { + rng = rand() % 53 + 1; + itemNew = bg_itemlist + rng; + } + // + if (itemNew->giType == IT_HOLDABLE || item->giType == IT_HOLDABLE || item->classname == "ammo_thermal") + { + + } + else + { + item = itemNew; + ent->classname == item->classname; + ent->item = item; + } + /* + IT_BAD, + IT_WEAPON, + IT_AMMO, + IT_ARMOR, + IT_HEALTH, + IT_HOLDABLE, + IT_BATTERY, + IT_HOLOCRON, + */ + /*ITM_NONE, // 0 + ITM_SABER_PICKUP, + ITM_BRYAR_PISTOL_PICKUP, + ITM_BLASTER_PICKUP, + ITM_DISRUPTOR_PICKUP, + ITM_BOWCASTER_PICKUP, + ITM_REPEATER_PICKUP, + ITM_DEMP2_PICKUP, + ITM_FLECHETTE_PICKUP, + ITM_ROCKET_LAUNCHER_PICKUP, + ITM_THERMAL_DET_PICKUP, + ITM_TRIP_MINE_PICKUP, + ITM_DET_PACK_PICKUP, + ITM_STUN_BATON_PICKUP, // 13 + + ITM_BOT_LASER_PICKUP, + ITM_EMPLACED_GUN_PICKUP, + ITM_TURRET_PICKUP, + ITM_MELEE, + ITM_ATST_MAIN_PICKUP, + ITM_ATST_SIDE_PICKUP, + ITM_TIE_FIGHTER_PICKUP, + ITM_RAPID_FIRE_CONC_PICKUP, + ITM_BLASTER_PISTOL_PICKUP, // 22 + + ITM_AMMO_FORCE_PICKUP, + ITM_AMMO_BLASTER_PICKUP, + ITM_AMMO_POWERCELL_PICKUP, + ITM_AMMO_METAL_BOLTS_PICKUP, + ITM_AMMO_ROCKETS_PICKUP, + ITM_AMMO_EMPLACED_PICKUP, + ITM_AMMO_THERMAL_PICKUP, + ITM_AMMO_TRIPMINE_PICKUP, + ITM_AMMO_DETPACK_PICKUP, // 31 + + ITM_FORCE_HEAL_PICKUP, + ITM_FORCE_LEVITATION_PICKUP, + ITM_FORCE_SPEED_PICKUP, + ITM_FORCE_PUSH_PICKUP, + ITM_FORCE_PULL_PICKUP, + ITM_FORCE_TELEPATHY_PICKUP, + ITM_FORCE_GRIP_PICKUP, + ITM_FORCE_LIGHTNING_PICKUP, + ITM_FORCE_SABERTHROW_PICKUP, // 40 + + ITM_BATTERY_PICKUP, + ITM_SEEKER_PICKUP, + ITM_SHIELD_PICKUP, + ITM_BACTA_PICKUP, + ITM_DATAPAD_PICKUP, + ITM_BINOCULARS_PICKUP, + ITM_SENTRY_GUN_PICKUP, + ITM_LA_GOGGLES_PICKUP, // 48 + + ITM_MEDPAK_PICKUP, + ITM_SHIELD_SM_PICKUP, + ITM_SHIELD_LRG_PICKUP, + ITM_GOODIE_KEY_PICKUP, + ITM_SECURITY_KEY_PICKUP, // 53 + + ITM_NUM_ITEMS // 54 + */ + } + // Set bounding box for item VectorSet( ent->mins, item->mins[0],item->mins[1] ,item->mins[2]); VectorSet( ent->maxs, item->maxs[0],item->maxs[1] ,item->maxs[2]); diff --git a/code/game/g_misc_model.cpp b/code/game/g_misc_model.cpp index 88c5f2f5..c9ea4f3d 100644 --- a/code/game/g_misc_model.cpp +++ b/code/game/g_misc_model.cpp @@ -422,7 +422,7 @@ void SP_misc_model_gun_rack( gentity_t *ent ) // Posto : I might be hated for this, but randomizing weapons here should be the best if (cg_enableRandomizer.integer) { - itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + //itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 2, ( i - 1 ) * 9 + crandom() * 2, ofz[i] ); } @@ -603,7 +603,7 @@ void spawn_rack_goods( gentity_t *ent ) // Posto : I might be hated for this, but randomizing ammos here should be the best if (cg_enableRandomizer.integer) { - itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); + //itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 0.5f, (i-1)* 8, 7.0f ); } @@ -646,7 +646,7 @@ void spawn_rack_goods( gentity_t *ent ) // Posto : Randomize the weapon here if (cg_enableRandomizer.integer) { - it = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); + //it = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); } GunRackAddItem( it, ent->s.origin, ent->s.angles, crandom() * 2, ( random() * 6 + 4 ) * pos, v_off ); } diff --git a/code/speedrun/speedrun_timer_includes.cpp b/code/speedrun/speedrun_timer_includes.cpp index e34ae22c..035b2b98 100644 --- a/code/speedrun/speedrun_timer_includes.cpp +++ b/code/speedrun/speedrun_timer_includes.cpp @@ -1,6 +1,13 @@ #include "speedrun_timer_includes.h" #include "../../server/exe_headers.h" +/* +// Randomizer +//#include "../cgame/cg_main.cpp" +extern vmCvar_t cg_enableRandomizer; +extern vmCvar_t cg_useSetSeed; +extern vmCvar_t cg_setSeed; +*/ namespace { @@ -15,6 +22,16 @@ void SpeedrunTimerPrint(const char* levelTimeString, totalTimeString); } Com_Printf(S_COLOR_RED "=========================\n"); + // Randomizer + /* + if (cg_enableRandomizer.integer) + { + Com_Printf(S_COLOR_RED "=========================\n"); + Com_Printf(S_COLOR_GREEN "Randomizer Seed: " S_COLOR_WHITE "%s\n", cg_setSeed); + Com_Printf(S_COLOR_RED "=========================\n"); + } + */ + } void SpeedrunTimerPrintNoNotify(const char* levelTimeString, From be6f5233e943fea901c2b1087d7fb9c8137da2d2 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Wed, 6 Nov 2024 21:58:54 +0000 Subject: [PATCH 20/62] Added enable_randomizer config --- code/demo/assets_randomizer.pk3 | Bin 15134 -> 15222 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/code/demo/assets_randomizer.pk3 b/code/demo/assets_randomizer.pk3 index 7f820a85def8e627800328cb122442ce1f019a4b..abcd498a4f4c25c72ceba63a0f0899ba822c2094 100644 GIT binary patch delta 1562 zcmV+#2IcvlcJ_9VD-j&7W?5d+{TvD$000XG0RR(|Z#ovSQV<${&2GXl41iz7>Ur7& z>^5ykW7391*=3iBpA?v&K~2%5J^gH_U4fA>S}P(*ltb&fQT#cw6DLWE_Jfoa!UJ+u z-X%wO&{z?ZNSwqI%jSa}-%mz*K3^#sNQrpJx3usHI)jXd^)X(h#@0Y(oZFe^X*mQ3zj~pMiX9X-QY0h-V=Pl@9vF22WLwZpAChs3 zHAfLdVptZXX3pjO`kSQg_1uAIz*D1 z<0q2@CAo|wOzg}h*$Woj!7^~RU{j*rK1_Dhtb5(#M8Zq|y*IqHEKTK9!~20i%=CKs zedveH{WCqW$9iE{y?@jZ?YCD zw5_RvTD-}yO%$HYa6^Fwc0esLu9#$z&=gASO7&9Mg}~lpf5c(KK7}3vjSs(w^Qu3H z5miJKDmWb0z7{HnT~DPFJyUZT8nEsO6a80|XQR000O8^R8xD$(^lvz#RYp z6%(^b9HJV3jC#|CfjIu$Z*k&zn^Ye6R#B!gsURiru)S0%n8E}xiW61Zr{A5O)DRLA zCtgxZlS&^N=MwDSxp#K%ALqK>8@7$ILn>@1nvbvQU1Vp~U$DVk2z%uJRilSyCPxd)K>{ zQsyn+lR6oeHe-*d?_MWpu5$umql4^^tohxQt~q=L61}GVG?s!!!$g(tL>sb(6gs!S z^}X)CnMQK0qhK%XzP-zO~1k{D7BPtiUG5+-Qo_c6C{`vLXP2k`n_7+uEUh5I}5 z`fkGLH$0vWRJ+Lae4wQ*$ZruHBF9FNTwSG=9JxOAdL9^R0q>4VlOKcC$E<4kdy z`bRBJxSo_`vE5SnD8%uDP#S~@!j^s=RTedWswTq8V!4O4Wuqm3eLXOmS&4XvGkR_Y z_!hQunvd|4a=aVJ2j|PE-$n8k`#QFTW|BRQE5uW~q#_kYYyxWBt8m^&Gx1vT) zVDx3@#sDKvfW{WM?n4@!;(~j z)<1wfRB4_{-%51$1Lsk{Eucgj(Agnu^}#Y78d)ThFzisGzvgfr|SgK=$kYbIhc_&G>M?4 zE@4{<2I#YOyx|q`s5|03Ddwo1(K3;TwJcSzy|4p+`$VAyc0kc0%9)f+`liq~g_ePl z!Y%|(A7@J$I9yU_AW)d_^Ek7*LTtwrQD~q%t-bA74CkIoPkoDm%f12Yo>I{VfBpiK z?>S)(9Ij?rUef&>3LF3c3k8#2Ix~On{+_IrFxvs{{+_IrFxvqws9M4jC))u~O928u z02BZK00;o{u4Y-uovnGm9RL6o69E7X03-ka0000003ZMW09+gZ0Cj0Eb7gdOa4v0S zZgmO(AOHXW000317yzfoo}892+X1J?o}892+W}YhTEY@1+W}BZ1qJ{B000gH00RIS M0RR9;IsgCw0LO>JGXMYp delta 1463 zcmexXHm_`gHlOSa_ejTg#d7zh85kxrZM4*sst@#UcHn9F?{#?dNA@3SC7m-~2+h>r zxACpSjDx!60>brsa}%3_{n&XwdK{B;yMA|F{Oo(N-U18%DkQZQG{;O0KiDs8vbBR( zW!{m;-k%+he{Y_8@9noPCQU(pS6BA=3xqu^)*P>xD&@}HTd3D8=^J2H{gO9e7_nw8UxbLnsn{nGr)kDkJ3!0+-N*%a#q|@u_zXd%! z?P~&J55U^a%e9um4Wy$qxo1<@Mt4uXuI6ZOhtNQw5pSGUjZwk1#*ve&6 z+heuKEUG)dsQAj9RlUg_G%rEYf_;N#V7~p?S1WA4?>g4o(*7a!;}`$%%;hIJnKoUm z{I>4QOu2~V>V0oqv@B;HJk=w!YHo&tHiKzF4$rQ}{?$h6nJa`GwN(?Vw{b;k|E@S3 ze`I&kk)Mt63o-ECp*k@z}eUHsME5_3cC^S0h|+i}3PyKlYti@b;1w;j6lf0w3O z`l@Fqc1dXjy$D$b|IQ1h?dKg9UEebAn2LnStQAJR8P3;cI6W8J zvG3X4?Uy~)O|^-4-~1?aS?l#e)roiF-|wkX(0S2t(NUj!VYkh;pcNvqcjMZB^hjlk zCe`No|NXqEep1VB&I=1{}pSVh38OQ8DQXy)luaxQ!olM!;zBBb;m%Xj5 zL}i$g+@zjwXBqAv^xOGUV*jMacOC9o#y2IZpR``{`i9yp&2JXxB4e`p9UC4p*2^e#doycXt~mbfO+nI1X}-|b53yGxniuIU?%EM3@geff zV$+FJzABcye)aE_XX^APhvwZamDF^sxBRho79= zpElJQPh=PO$+{tTvvGfo5_>;yz?6<+wa|$RHA@8f%!6*UAGrCqX6c>p(Ol9TBECN= zb;1f7Z_LYFw4rHJboI^6Ea!Bme!JJzbed}+<7@p$hxk8#SSPz%C88CRlebwJJI}nN zd*_kFZAKVvtQ=FJ4CDuRGcwsT;L2_)zzhch3P5Z)S;tyNFZVV3RggI_I=&EQ4l5f- PB{L98GBPl{w*>J3h=ivL From 7a78cd0f03b118bf39db8fcf4fdb264527c8897e Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Wed, 6 Nov 2024 23:58:25 +0000 Subject: [PATCH 21/62] Moved seed handling to RandomizerUtils class, applied this during map load and removed some rand() and srand() calls to ensure consistent results. Also commented out some checks against items spawning inside geometry - we have to accept this will happen or we will break on a lot of spawns --- code/game/NPC_spawn.cpp | 21 +--------------- code/game/g_items.cpp | 38 ++++++++++++++--------------- code/game/g_main.cpp | 17 ++++++++----- code/game/game.vcxproj | 5 ++++ code/game/game.vcxproj.filters | 9 +++++++ code/randomizer/RandomizerUtils.cpp | 26 ++++++++++++++++++++ code/randomizer/RandomizerUtils.h | 8 ++++++ 7 files changed, 79 insertions(+), 45 deletions(-) create mode 100644 code/randomizer/RandomizerUtils.cpp create mode 100644 code/randomizer/RandomizerUtils.h diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index b9da83fe..64e6f18e 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -13,6 +13,7 @@ #include "g_functions.h" #include "g_icarus.h" #include "wp_saber.h" +#include "..\randomizer\RandomizerUtils.h" extern cvar_t *g_sex; @@ -2799,14 +2800,6 @@ short tabLockedInNPC[tabSize] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, short currentTabPosition = 0; char lastKnownMap[32] = "first_iteration"; -//I hate working in c++ so much -void AddCharArrayToInt(char chars[], int* value) -{ - for (int i = 0; i < sizeof(chars); i++) { - *value += chars[i]; - } -} - void MapChanged() { //strcpy(lastKnownMap, level.mapname); @@ -2819,18 +2812,6 @@ void MapChanged() // We might have to lock Kyle, we will see what happen. // tabLockedInNPC[0] = 0; // currentTabPosition = 1; - - // We want to ensure seed consistenty per level - // i.e. for a given seed a player will always get the same enemy spawn for that level - // regardless of any other uses of rand() in the game. Thus we should set the seed - // on level change, and use the level string as a part of the seed to get - // unique enemy sets per level - if (cg_setSeed.string != "") { //If we have no set seed just use random seed -- should we warn user? - int seed = 0; - AddCharArrayToInt(cg_setSeed.string, &seed); - AddCharArrayToInt(level.mapname, &seed); - srand(seed); - } } void CheckIfMapChanged() diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index a2a2af41..462e8754 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -954,25 +954,25 @@ void FinishSpawningItem( gentity_t *ent ) { // drop to floor VectorSet( dest, ent->s.origin[0], ent->s.origin[1], MIN_WORLD_COORD ); gi.trace( &tr, ent->s.origin, ent->mins, ent->maxs, dest, ent->s.number, MASK_SOLID|CONTENTS_PLAYERCLIP, (EG2_Collision)0, 0 ); - if ( tr.startsolid ) - { - if ( &g_entities[tr.entityNum] != NULL ) - { - gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin), g_entities[tr.entityNum].classname ); - } - else - { - gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin) ); - } - assert( 0 && "item starting in solid"); -#ifndef FINAL_BUILD - if (!g_entities[ENTITYNUM_WORLD].s.radius){ //not a region - delayedShutDown = level.time + 100; - } -#endif - G_FreeEntity( ent ); - return; - } +// if ( tr.startsolid ) +// { +// if ( &g_entities[tr.entityNum] != NULL ) +// { +// gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin), g_entities[tr.entityNum].classname ); +// } +// else +// { +// gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin) ); +// } +// //assert( 0 && "item starting in solid"); +//#ifndef FINAL_BUILD +// //if (!g_entities[ENTITYNUM_WORLD].s.radius){ //not a region +// // delayedShutDown = level.time + 100; +// //} +//#endif +// G_FreeEntity( ent ); +// return; +// } // allow to ride movers ent->s.groundEntityNum = tr.entityNum; diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index d6ef680a..1212820c 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -17,6 +17,7 @@ #include #include +#include "../randomizer/RandomizerUtils.h" using namespace std::chrono; @@ -623,6 +624,9 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons if (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) { RegenerateSeed(); } + char seed[MAX_STRING_CHARS]; + gi.Cvar_VariableStringBuffer("cg_setSeed", seed, sizeof(seed)); + RandomizerUtils::seedRandomizer(seed, mapname); giMapChecksum = checkSum; g_eSavedGameJustLoaded = eSavedGameJustLoaded; g_qbLoadTransition = qbLoadTransition; @@ -631,7 +635,7 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons gi.Printf ("gamename: %s\n", GAMEVERSION); gi.Printf ("gamedate: %s\n", __DATE__); - srand( randomSeed ); + //srand( randomSeed ); Randomizer should control seeding G_InitCvars(); @@ -706,13 +710,14 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons gi.Printf ("-----------------------------------\n"); + //Removed below so as not to interfere with consistent randomizer results //randomize the rand functions - byte num_calls = (byte)timeGetTime(); + //byte num_calls = (byte)timeGetTime(); - for(i = 0; i < (int)num_calls; i++) - { - rand(); - } + //for(i = 0; i < (int)num_calls; i++) + //{ + // rand(); + //} if ( navCalculatePaths ) {//not loaded - need to calc paths diff --git a/code/game/game.vcxproj b/code/game/game.vcxproj index f2f7bc5a..fc8d26ce 100644 --- a/code/game/game.vcxproj +++ b/code/game/game.vcxproj @@ -718,6 +718,10 @@ Use common_headers.h + + false + NotUsing + true true @@ -1477,6 +1481,7 @@ + diff --git a/code/game/game.vcxproj.filters b/code/game/game.vcxproj.filters index 20c3b76d..2c32f253 100644 --- a/code/game/game.vcxproj.filters +++ b/code/game/game.vcxproj.filters @@ -41,6 +41,9 @@ {52e1452b-6841-4ef6-8053-b87ef213c431} + + {ab905c46-58e7-4180-adf0-c696239b47ad} + @@ -442,6 +445,9 @@ speedrun\speedrun_timer_q3 + + randomizer + @@ -678,6 +684,9 @@ speedrun\speedrun_timer_q3 + + randomizer + diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp new file mode 100644 index 00000000..35769853 --- /dev/null +++ b/code/randomizer/RandomizerUtils.cpp @@ -0,0 +1,26 @@ +#include +#include +#include "../game/q_shared.h" +#include "RandomizerUtils.h" + +static void AddCharArrayToInt(string seedString, int* value) +{ + for (int i = 0; i < seedString.size(); i++) { + *value += seedString[i]; + } +} + +void RandomizerUtils::seedRandomizer(string seedString, string levelName) +{ + // We want to ensure seed consistenty per level + // i.e. for a given seed a player will always get the same enemy spawn for that level + // regardless of any other uses of rand() in the game. Thus we should set the seed + // on level change, and use the level string as a part of the seed to get + // unique enemy sets per level + if (seedString != "") { //If we have no set seed just use random seed -- should we warn user? + int seed = 0; + AddCharArrayToInt(seedString, &seed); + AddCharArrayToInt(levelName, &seed); + srand(seed); + } +} diff --git a/code/randomizer/RandomizerUtils.h b/code/randomizer/RandomizerUtils.h new file mode 100644 index 00000000..4787535c --- /dev/null +++ b/code/randomizer/RandomizerUtils.h @@ -0,0 +1,8 @@ +#pragma once +#include + +class RandomizerUtils +{ + public: static void seedRandomizer(string seedString, string levelName); +}; + From 76f3c7033afc7cd6b3369f2ff9f113e66b6c4538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 7 Nov 2024 13:42:31 +0100 Subject: [PATCH 22/62] Encapsulated more code between the randomizer check, and moved the debug page to "randomizer_info" in the file RandomizerUtils.cpp --- code/base/assets_randomizer.pk3 | Bin 15225 -> 15222 bytes code/base/jk2config.cfg | 4 +- code/cgame/cg_main.cpp | 4 +- code/game/NPC_spawn.cpp | 68 ----------------- code/game/g_items.cpp | 72 ++++++++++-------- code/game/g_main.cpp | 60 +++++---------- code/game/g_svcmds.cpp | 10 +-- code/randomizer/RandomizerUtils.cpp | 109 +++++++++++++++++++++++++++- code/randomizer/RandomizerUtils.h | 7 +- 9 files changed, 185 insertions(+), 149 deletions(-) diff --git a/code/base/assets_randomizer.pk3 b/code/base/assets_randomizer.pk3 index 2799209b8b780fcec38e01efa791aa20359ad070..abcd498a4f4c25c72ceba63a0f0899ba822c2094 100644 GIT binary patch delta 1520 zcmVUr7&>^5ykW7391*=3iB zpA?v&K~2%5J^gH_U4fA>S}P(*ltb&fQT#cw6DLWE_Jfoa!UJ+u-X%wO&{z?ZNSwqI z%jSa}-%mz*K3^#sNQrpJx3usHI)jXd^)X(h#@0Y(oZFe^X*mQ3zj~pMiX9X-QY0h-V=Pl@9vF22WLwZpAChs3HAfLdVptZXX3pjO`kSQg_1uAIz*D1<0q2@CAo|wOzg}h z*$Woj!7^~RU{j*rK1_Dhtb5(#M8Zq|y*IqHEKTK9!~20i%=CKsedveH{WCqW$9iE{ zy?@jZ?YCDw5_RvTD-}yO%$HY za6^Fwc0esLu9#$z&=gASO7&9Mg}~lpf5c(KK7}3vjSs(w^Qu3H5miJKDmWb0z7{Hn zT~DPFJyUZT8nEsO6a70|XQR000O8^R8xD$(^lvz#RYp6|;66qZ)sVdeer1 zIR4ykapHNKR37(MQKm7eASLjyy;Lcf!UQpj6II%$-<_S*5E2t7UQ$bwN*@~M671i( zcXsX{=eph-wvDnwDr_g3kFV-oWM|c1w_0x_nB%5J%hwCE_wajLVd;O}72`8ib7Wm6 ziWE9ksRWL5E%RCM{Ow_~Tm*kV=@fcmBW(Gu@*5plQXU+8*SnWe<}KfoIvJKWV~?os zUMFa-a{^(bgY1v2`Q4SSIeZ2Zy{7#%mV!pZM3wGD8?uHJI=8^}z3#r5Msls>`6`?i zuQDxW9aj>`-Sy6^6JbFIv<`Y%2wmi{l|-c&>gGDcXVh4$5UX=L>YslXMq=*H^?j2- zpD(oECoIj97*Y;T(LM$eCTQmOF}HC00rk)a@cLXBUB=;s`#bXbZo=p{Jf03zyU6u? zprtLyZxJ0L$3~G{U8R*AxjyxJ9vEr??~Y27AA{A$tZNi(jgDUWM=egco|I&<-BS4| z#PNer8iWbLmVO;o7BzpWCc?>Lxreo7qa}ZRJusSCiFk-JdTs{z7PfMlkMNUnyc@^| z=gX+yMe-K=I<|#ol0A+q#xHp5YewtF?hstO+l3h#uAxx3qDD?&^kwJ903%O;#um8l zLmHgq7|AE;Mm}!XG+|Nl<_^J-&aDBDj{UFSx^GIN90u6z1rdMNKY%?{aVY@PB-*ka zJDgbJhC^u(zDtWWD5^HHi5rChpT#~J6G>GcLiMg1uZ~oZxAeuSvjcs0n=}_Wn2|IziJ+w}VOt3X=(Baa;T7?y zJK{Vk=BS;~GLeV1ELE_*umgYlM4<(CK+z(~nUqcXrqDNqmVuGNE(A^=XGZ;0zUv0000080Q0V9S;?KPdB7b2 z02LDf01W^n000000000W00017lP^0QE~m$yoR%=#0jI~FoR%=#0ax}~!V)Lj0Z>Z? W1^@s600RI602u)Q07p6i0001Cd%Y0= delta 1523 zcmVh2Ub|q1_JbKKggfLaxe01JXfhESNIZ$B zFU<#~xgX5+X0uo1NQroeQ`-0h9YV-%eSt@!@opeD&UMh?2?#Cro?E2hF6}j7_OK{_ z$}I8LS85lBS`NYKNiR%LaRY^g6bXsI*q4-=14eCtYzw*=Lo$wuIEo+={jw;PMf;6K z=1mU48GW|_JU%DG+mH(Nn@D6czPRKDz_Me1r~03<{79pNAe0ZN4w0nWag#}cl3eyAOzg}h z*$cKjz%p>QU{j*r-p}f&*!Q}{M8f0bZT#|2S83JY1OZv=X!oVeg)=YRIQ;#8gxmCq z-cy?g7x*E=wp7?5e?<-+2jD2N$eCmj-xNxO!%hmj5I7!9=Ip-DDRdBMo%r>)`Sb^3 zL=_Q*3aW1HbE{$~&r~XvvPUj`118aadIGG%*Evb=Yqd-_Z8)p(bkBw=S4O0nh z)P{jDeBOUC;@nnRj=imbs#IF25;(M%RR9B9L5$)=`}aFzCzuUMHcq?=UabUN;y8)@ z%rO3#H`aB%H*6auhgg_8n%h_P&PHd&k6Wy_;mvT-qT%ZWnp^n2sj&2WH^uNm)f`!u z14Rm*ic|uJsh0WFd;0M(TFkvabbku%*zg;^tNe|I%qb5Joon6KQsxcclRD~`w#pV! z&t4{IuEzwzLO&)v8+stbeY>kGV`=b^ooKK39&}^!F z;A8)RFDrx*!WMrY6ecyQB7eflWVwU6WrGFZ?GB7QD-jQ2Li=WbZ(%Fle1PAW%K0DvKwIYEQqk~0e|cui%S6*N5Piu z+2O<@I~>Xi;is&z1VvRw7O|r+;Ii09Z6Yb_L#WnO{ne7nCdq{@wL@xS`7b%1EJFDU zt3xE|cB;vwf;PEyBus40CG{7mHE%m`Hel06qEAfHMn^)4vn%Mn`G+-~<8L z@FVU^hzu=Ig(nr!iGQu&?%z5>GjMTKR!JIGiJ-+cVOt7@ti@%# z;T7?yHR4z3|IkQ`oW(z zY?bVqa8}^yen+&oWlS{|PCDf;YscYzxW8E0Hgd+PYwp?yt@Opuf0IW#VF|XmMp=6X zXSNNKu{t= 6) // The help page, when we reach an undefined number. - { - gi.Printf(S_COLOR_RED"Oops, it seems that you didn't provide a valid page number.\n"); - gi.Printf(S_COLOR_RED"Welcome to the default page.\n"); - gi.Printf(S_COLOR_MAGENTA"Here is the correct syntax : randomizer_debug .\n"); - gi.Printf(S_COLOR_WHITE"Page 1 : General information.\n"); - gi.Printf(S_COLOR_WHITE"Page 2 : Currently generated NPCs on this map (%s).\n",level.mapname); - gi.Printf(S_COLOR_WHITE"Page 3 : Rules for NPCs.\n"); - gi.Printf(S_COLOR_WHITE"Page 4 : Rules for maps.\n"); - gi.Printf(S_COLOR_WHITE"Page 5 : Rules for weapons / ammo\n"); - gi.Printf(S_COLOR_WHITE"Page 6 : Todo\n"); - return; // So that we won't go to the switch bellow - } - switch (page) - { - case 1: // General informations - gi.Printf(S_COLOR_MAGENTA"NPC spawns are determined during the first load of a map. Meaning that if youn load a map, quicksave and quickload, the NPCs will always be the sames.\n"); - gi.Printf(S_COLOR_MAGENTA"But, if you reload the map using the save files that the game generate, a new set of random NPCs will be generated.\n"); - gi.Printf(S_COLOR_MAGENTA"All random NPCs remplacing ones carrying keys to open doors (eg : kejim_base), will also carry said keys. So kill them to get keys (even if they are friendly or neutral) !\n"); - break; - case 2: // Informations about tabLockedInNPC - gi.Printf(S_COLOR_MAGENTA"The maximum number of unique NPCs authorized is currently %d.\n",tabSize); - gi.Printf(S_COLOR_MAGENTA"The map is : %s.\n", level.mapname); - if (tabSize != 50) - { - for (int i = 0; i < tabSize; i++) - { - gi.Printf(S_COLOR_CYAN"NPC number %d is : %s.\n", i + 1, GetNPCNames(tabLockedInNPC[i])); - } - } - else gi.Printf(S_COLOR_CYAN"ALL NPC can spawn (except the ones banned due to them being unstable / broken / run-killers (Desann)).\n"); - - break; - case 3: // Which NPC are forced no matter which map (Jan for exemple, not having her breaks the first map and yavin_swamp cutscene as far as I know). Update this if needed - gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now that's how it is.\n"); - gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will ALWAYS spawn as themselves, no matter which map you are on :\n"); - gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, ATST, Mark1, Mark2 (Chicken robot), R2D2, R5D2 and SeekerDrones.\n"); - gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will NEVER randomly spawn, no matter which map you are on :\n"); - gi.Printf(S_COLOR_CYAN"Tavion, Desann, ATST, Chicken Robot (Mark2) and bugged monsters (Glider...)\n"); - break; - case 4: // Map specific locked NPCs (thinking about the officer in assembly to open the first door)(maybe other NPCs can do it, but idk). Update this if needed. - gi.Printf(S_COLOR_MAGENTA"Some spawn on specific maps are forced, so that we don't softlock the game.\n"); - gi.Printf(S_COLOR_MAGENTA"Unfortunatly, it means that every iteration of the same NPC on this map will spawn normally.\n"); - gi.Printf(S_COLOR_MAGENTA"Here is the list of maps that have specific NPC locked :\n"); - gi.Printf(S_COLOR_CYAN"Todo.\n"); - break; - case 5: // - gi.Printf(S_COLOR_MAGENTA"Here are the general rules for how weapons will work :\n"); - gi.Printf(S_COLOR_CYAN"Weapons are replaced by other weapons (a E-11 blaster can become a bowcaster).\n"); - gi.Printf(S_COLOR_CYAN"Ammo are replaced with another king of ammo. Explosives are considered ammo, so you can find them here and not in weapons slots.\n"); - gi.Printf(S_COLOR_CYAN"Items on the ground (like the bowcaster on artus_mines or bactas in general) remain unchanged.\n"); - gi.Printf(S_COLOR_CYAN"Health pack on weapon/ammo rack are constants too.\n"); - break; - default: - return; - } - -} void SP_NPC_Spawn_Random(gentity_t* self) { diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 462e8754..d9807af4 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -803,22 +803,31 @@ void FinishSpawningItem( gentity_t *ent ) { // For tests prupose only int rng = rand() % 54; itemNew = bg_itemlist + rng; - while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 1)) // No saber, no baton, no strange items - { - rng = rand() % 53 + 1; - itemNew = bg_itemlist + rng; - } - // - if (itemNew->giType == IT_HOLDABLE || item->giType == IT_HOLDABLE || item->classname == "ammo_thermal") + // No saber, no baton, no strange items. And no force (for now) + if ((strcmp(level.mapname, "yavin_trial"))) { + while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 1) || (itemNew->giTag >= 32 && itemNew->giTag <= 40) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) + { + rng = rand() % 53 + 1; + itemNew = bg_itemlist + rng; + } + // + if (itemNew->giType == IT_HOLOCRON) + { + } + else + { + item = itemNew; + ent->classname == item->classname; + ent->item = item; + } } - else + else // Don't do anything if we are in trial, we CAN'T not get force power { - item = itemNew; - ent->classname == item->classname; - ent->item = item; + } + /* IT_BAD, IT_WEAPON, @@ -954,25 +963,28 @@ void FinishSpawningItem( gentity_t *ent ) { // drop to floor VectorSet( dest, ent->s.origin[0], ent->s.origin[1], MIN_WORLD_COORD ); gi.trace( &tr, ent->s.origin, ent->mins, ent->maxs, dest, ent->s.number, MASK_SOLID|CONTENTS_PLAYERCLIP, (EG2_Collision)0, 0 ); -// if ( tr.startsolid ) -// { -// if ( &g_entities[tr.entityNum] != NULL ) -// { -// gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin), g_entities[tr.entityNum].classname ); -// } -// else -// { -// gi.Printf (S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin) ); -// } -// //assert( 0 && "item starting in solid"); -//#ifndef FINAL_BUILD -// //if (!g_entities[ENTITYNUM_WORLD].s.radius){ //not a region -// // delayedShutDown = level.time + 100; -// //} -//#endif -// G_FreeEntity( ent ); -// return; -// } + if (!cg_enableRandomizer.integer) // During normal gameplay, we have to keep this code to be as faithful to the base game + { + if (tr.startsolid) + { + if (&g_entities[tr.entityNum] != NULL) + { + gi.Printf(S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin), g_entities[tr.entityNum].classname); + } + else + { + gi.Printf(S_COLOR_RED"FinishSpawningItem: removing %s startsolid at %s (in a %s)\n", ent->classname, vtos(ent->s.origin)); + } + assert( 0 && "item starting in solid"); +#ifndef FINAL_BUILD + if (!g_entities[ENTITYNUM_WORLD].s.radius){ //not a region + delayedShutDown = level.time + 100; + } +#endif + G_FreeEntity(ent); + return; + } + } // allow to ride movers ent->s.groundEntityNum = tr.entityNum; diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index 1212820c..b9126b0c 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -16,11 +16,8 @@ #include "../cgame/cg_local.h" // yeah I know this is naughty, but we're shipping soon... #include -#include #include "../randomizer/RandomizerUtils.h" -using namespace std::chrono; - extern CNavigator navigator; static int navCalcPathTime = 0; int eventClearTime = 0; @@ -573,32 +570,6 @@ void G_InitCvars( void ) { g_iscensored = gi.cvar( "ui_iscensored", "0", CVAR_ARCHIVE|CVAR_ROM|CVAR_INIT|CVAR_CHEAT|CVAR_NORESTART ); } -void RegenerateSeed(void) { - //Reinitialise randomizer seed value if we're not using setSeed - if (gi.Cvar_VariableIntegerValue("cg_useSetSeed") != 1) - { - //Get System Epoch Time - auto duration = system_clock::now().time_since_epoch(); - - //Convert duration to milliseconds - long milliseconds - = chrono::duration_cast( - duration) - .count(); - - //Hash the time to get a consistent length seed - hash hasher; - string s = to_string(milliseconds); - size_t hash = hasher(s); - - //Convert to string - string hashString = to_string(hash); - - //Update seed value - gi.cvar_set("cg_setSeed", hashString.c_str()); - //Cvar_Set("cg_setSeed", hashString.c_str()); - } -} /* ============ @@ -621,12 +592,17 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons int i; //Reset randomiser seed on new load of kejim_post - if (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) { - RegenerateSeed(); + + if (cg_enableRandomizer.integer) + { + if (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) { + RandomizerUtils::RegenerateSeed(); + } + char seed[MAX_STRING_CHARS]; + gi.Cvar_VariableStringBuffer("cg_setSeed", seed, sizeof(seed)); + RandomizerUtils::seedRandomizer(seed, mapname); } - char seed[MAX_STRING_CHARS]; - gi.Cvar_VariableStringBuffer("cg_setSeed", seed, sizeof(seed)); - RandomizerUtils::seedRandomizer(seed, mapname); + giMapChecksum = checkSum; g_eSavedGameJustLoaded = eSavedGameJustLoaded; g_qbLoadTransition = qbLoadTransition; @@ -635,7 +611,8 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons gi.Printf ("gamename: %s\n", GAMEVERSION); gi.Printf ("gamedate: %s\n", __DATE__); - //srand( randomSeed ); Randomizer should control seeding + // Randomizer should control seeding, in normal game it's the same code + if(!cg_enableRandomizer.integer) srand( randomSeed ); G_InitCvars(); @@ -712,12 +689,15 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons //Removed below so as not to interfere with consistent randomizer results //randomize the rand functions - //byte num_calls = (byte)timeGetTime(); + if (!cg_enableRandomizer.integer) + { + byte num_calls = (byte)timeGetTime(); - //for(i = 0; i < (int)num_calls; i++) - //{ - // rand(); - //} + for (i = 0; i < (int)num_calls; i++) + { + rand(); + } + } if ( navCalculatePaths ) {//not loaded - need to calc paths diff --git a/code/game/g_svcmds.cpp b/code/game/g_svcmds.cpp index fb06bd8f..a881adec 100644 --- a/code/game/g_svcmds.cpp +++ b/code/game/g_svcmds.cpp @@ -8,7 +8,7 @@ #include "wp_saber.h" //#include <..\game\NPC_spawn.cpp> -extern void RandomizerDebugCommandCatcher(int page); // It's declared in NPC_spawn.cpp +extern void RandomizerInfoCommandCatcher(int page); // It's declared in NPC_spawn.cpp extern void Q3_SetViewEntity(int entID, const char *name); extern qboolean G_ClearViewEntity( gentity_t *ent ); @@ -928,13 +928,13 @@ qboolean ConsoleCommand( void ) { } // Posto : This is caught first - if (Q_stricmp(cmd, "randomizer_debug") == 0) + if (Q_stricmp(cmd, "randomizer_info") == 0) { - // After randomizer_debug, we want to catch the first arg. If not set (page is a 0 size char array), send page -1 (equivalent to a help page) + // After randomizer_info, we want to catch the first arg. If not set (page is a 0 size char array), send page -1 (equivalent to a help page) // Does that mean that a page 0 exist ? No, if a page is not referenced, we print the help page. char* page = gi.argv(1); - if (strlen(page)==0) RandomizerDebugCommandCatcher(-1); // Show the 'help page' - else RandomizerDebugCommandCatcher(atoi(page)); + if (strlen(page)==0) RandomizerInfoCommandCatcher(-1); // Show the 'help page' + else RandomizerInfoCommandCatcher(atoi(page)); } return qfalse; diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp index 35769853..1f30ea61 100644 --- a/code/randomizer/RandomizerUtils.cpp +++ b/code/randomizer/RandomizerUtils.cpp @@ -1,8 +1,23 @@ +// leave this line at the top for all g_xxxx.cpp files... +#include "../game/g_headers.h" + #include #include #include "../game/q_shared.h" +#include +#include "../game/g_local.h" +//#include "../game/g_headers.h" #include "RandomizerUtils.h" +using namespace std::chrono; + +// Randomizer +extern vmCvar_t cg_enableRandomizer; +extern vmCvar_t cg_useSetSeed; +extern vmCvar_t cg_setSeed; +// To access the game +extern game_import_t gi; + static void AddCharArrayToInt(string seedString, int* value) { for (int i = 0; i < seedString.size(); i++) { @@ -10,7 +25,7 @@ static void AddCharArrayToInt(string seedString, int* value) } } -void RandomizerUtils::seedRandomizer(string seedString, string levelName) +void RandomizerUtils::seedRandomizer(std::string seedString, std::string levelName) { // We want to ensure seed consistenty per level // i.e. for a given seed a player will always get the same enemy spawn for that level @@ -24,3 +39,95 @@ void RandomizerUtils::seedRandomizer(string seedString, string levelName) srand(seed); } } + +void RandomizerUtils::RegenerateSeed() +{ + //Reinitialise randomizer seed value if we're not using setSeed + if (cg_enableRandomizer.integer) + { + //Get System Epoch Time + auto duration = system_clock::now().time_since_epoch(); + + //Convert duration to milliseconds + long milliseconds + = chrono::duration_cast( + duration) + .count(); + + //Hash the time to get a consistent length seed + hash hasher; + string s = to_string(milliseconds); + size_t hash = hasher(s); + + //Convert to string + string hashString = to_string(hash); + + //Update seed value + gi.cvar_set("cg_setSeed", hashString.c_str()); + //Cvar_Set("cg_setSeed", hashString.c_str()); + + } +} + +void RandomizerInfoCommandCatcher(int page) +{ + // List of colors + //S_COLOR_BLACK, S_COLOR_BLUE, S_COLOR_CYAN, S_COLOR_GREEN, S_COLOR_MAGENTA, S_COLOR_RED, S_COLOR_WHITE, S_COLOR_YELLOW + + //gi.Printf(S_COLOR_GREEN"We are getting to this function, we can log things here !\n"); + //gi.Printf(S_COLOR_GREEN"Page number received : %d\n",page); + + // Just for information : the console is 30 lines long, + // Even if the Randomizer is disabled, randomizer_debug (maybe renamed to randomizer_info) will still print this page. + if (page <= 0 || page >= 6) // The help page, when we reach an undefined number. + { + gi.Printf(S_COLOR_RED"Oops, it seems that you didn't provide a valid page number.\n"); + gi.Printf(S_COLOR_RED"Welcome to the default page.\n"); + gi.Printf(S_COLOR_RED"IT'S STILL IN CONSTRUCTION !\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the correct syntax : randomizer_debug .\n"); + gi.Printf(S_COLOR_WHITE"Page 1 : General information.\n"); + gi.Printf(S_COLOR_WHITE"Page 2 : Currently generated NPCs on this map (%s).\n", level.mapname); + gi.Printf(S_COLOR_WHITE"Page 3 : Rules for NPCs.\n"); + gi.Printf(S_COLOR_WHITE"Page 4 : Rules for maps.\n"); + gi.Printf(S_COLOR_WHITE"Page 5 : Rules for weapons / ammo\n"); + gi.Printf(S_COLOR_WHITE"Page 6 : Todo\n"); + return; // So that we won't go to the switch bellow + } + switch (page) + { + case 1: // General informations + gi.Printf(S_COLOR_MAGENTA"NPC spawns are determined during the first load of a map. Meaning that if youn load a map, quicksave and quickload, the NPCs will always be the sames.\n"); + gi.Printf(S_COLOR_MAGENTA"But, if you reload the map using the save files that the game generate, a new set of random NPCs will be generated.\n"); + gi.Printf(S_COLOR_MAGENTA"All random NPCs remplacing ones carrying keys to open doors (eg : kejim_base), will also carry said keys. So kill them to get keys (even if they are friendly or neutral) !\n"); + break; + case 2: // Informations about tabLockedInNPC + gi.Printf(S_COLOR_MAGENTA"The maximum number of unique NPCs authorized is currently all !\n"); + gi.Printf(S_COLOR_MAGENTA"The map is : %s.\n", level.mapname); + gi.Printf(S_COLOR_CYAN"ALL NPC can spawn (except the ones banned due to them being unstable / broken / run-killers (Desann)).\n"); + + break; + case 3: // Which NPC are forced no matter which map (Jan for exemple, not having her breaks the first map and yavin_swamp cutscene as far as I know). Update this if needed + gi.Printf(S_COLOR_MAGENTA"Some spawn have been forced. It might not be necessarry, but for now that's how it is.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will ALWAYS spawn as themselves, no matter which map you are on :\n"); + gi.Printf(S_COLOR_CYAN"Kyle, Jan, Luke, Lando, Tavion, Desann, MonMothma, Reelo, Galak, Bartender, Prisoner, Morgan, Ugnaught, MouseDroid, ATST, Mark1, Mark2 (Chicken robot), R2D2, R5D2 and SeekerDrones.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of characters that will NEVER randomly spawn, no matter which map you are on :\n"); + gi.Printf(S_COLOR_CYAN"Tavion, Desann, ATST, Chicken Robot (Mark2) and bugged monsters (Glider...)\n"); + break; + case 4: // Map specific locked NPCs (thinking about the officer in assembly to open the first door)(maybe other NPCs can do it, but idk). Update this if needed. + gi.Printf(S_COLOR_MAGENTA"Some spawn on specific maps are forced, so that we don't softlock the game.\n"); + gi.Printf(S_COLOR_MAGENTA"Unfortunatly, it means that every iteration of the same NPC on this map will spawn normally.\n"); + gi.Printf(S_COLOR_MAGENTA"Here is the list of maps that have specific NPC locked :\n"); + gi.Printf(S_COLOR_CYAN"Todo.\n"); + break; + case 5: // + gi.Printf(S_COLOR_MAGENTA"Here are the general rules for how weapons will work :\n"); + gi.Printf(S_COLOR_CYAN"Weapons are replaced by other weapons (a E-11 blaster can become a bowcaster).\n"); + gi.Printf(S_COLOR_CYAN"Ammo are replaced with another king of ammo. Explosives are considered ammo, so you can find them here and not in weapons slots.\n"); + gi.Printf(S_COLOR_CYAN"Items on the ground (like the bowcaster on artus_mines or bactas in general) remain unchanged.\n"); + gi.Printf(S_COLOR_CYAN"Health pack on weapon/ammo rack are constants too.\n"); + break; + default: + return; + } + +} \ No newline at end of file diff --git a/code/randomizer/RandomizerUtils.h b/code/randomizer/RandomizerUtils.h index 4787535c..54899e3f 100644 --- a/code/randomizer/RandomizerUtils.h +++ b/code/randomizer/RandomizerUtils.h @@ -1,8 +1,13 @@ #pragma once +#include #include class RandomizerUtils { - public: static void seedRandomizer(string seedString, string levelName); + private: + + public: + static void seedRandomizer(std::string seedString, std::string levelName); + static void RegenerateSeed(); }; From 06ff7f0ab196b3482fdee6c8c68f4df01b92d42f Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Thu, 7 Nov 2024 17:45:59 +0000 Subject: [PATCH 23/62] Allow interactions with items clipped partially into geometry --- code/game/g_items.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index d9807af4..9621c66f 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -769,6 +769,15 @@ void Use_Item( gentity_t *ent, gentity_t *other, gentity_t *activator ) //====================================================================== +void updateItemMinsMaxs(gitem_t *item) { + item->mins[0] = item->mins[0] * 1.5; + item->mins[1] = item->mins[1] * 1.5; + item->mins[2] = item->mins[2] * 1.5; + item->maxs[0] = item->maxs[0] * 1.5; + item->maxs[1] = item->maxs[1] * 1.5; + item->maxs[2] = item->maxs[2] * 1.5; +} + /* ================ FinishSpawningItem @@ -819,6 +828,7 @@ void FinishSpawningItem( gentity_t *ent ) { else { item = itemNew; + updateItemMinsMaxs(item); //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry ent->classname == item->classname; ent->item = item; } From 6deb7ed0a972799ab89cd003fcf2c1ef8335af2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 8 Nov 2024 21:50:48 +0100 Subject: [PATCH 24/62] Small push --- code/game/NPC_spawn.cpp | 35 +++++++++++++++++++++++++++-- code/game/g_items.cpp | 27 +++++++++++----------- code/randomizer/RandomizerUtils.cpp | 2 +- 3 files changed, 48 insertions(+), 16 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index fc0b7179..6c318355 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -3452,6 +3452,17 @@ void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys CheckForceSpawn(self, "t198", "Gran"); return; } + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (CheckForceSpawn(self, "back_squad1", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad2", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad3", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad4", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad1", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad2", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad3", "Gran")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad4", "Gran")) return; // For Lando in the hangar + } SP_NPC_Spawn_Random(self); } else SP_NPC_Gran(self); @@ -3470,7 +3481,15 @@ void SP_NPC_Rodian_Random(gentity_t* self) { if (CheckForceSpawn(self, "reelo_thug", "Rodian")) return; // The guys with Reelo at the end of the mission if (CheckForceSpawn(self, "end_thug", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "bea", "Rodian")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "back_squad1", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad2", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad3", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad4", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad1", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad2", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad3", "Rodian")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad4", "Rodian")) return; // For Lando in the hangar } SP_NPC_Spawn_Random(self); } @@ -3486,6 +3505,18 @@ void SP_NPC_Weequay_Random(gentity_t* self) if (CheckForceSpawn(self, "reelo_thug", "Weequay")) return; // The guys with Reelo at the end of the mission if (CheckForceSpawn(self, "end_thug", "Weequay")) return; // The guys with Reelo at the end of the mission if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission + if (CheckForceSpawn(self, "back_squad1", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad2", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad3", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "back_squad4", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad1", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad2", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad3", "Weequay")) return; // For Lando in the hangar + if (CheckForceSpawn(self, "front_squad4", "Weequay")) return; // For Lando in the hangar + } + if (strcmp(lastKnownMap, "ns_hideout") == 0) + { + if (CheckForceSpawn(self, "trap", "Weequay")) return; // The guys after the 5 turrets } SP_NPC_Spawn_Random(self); } @@ -3819,7 +3850,7 @@ void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + SP_NPC_Droid_Mouse(self); } else SP_NPC_Droid_Mouse(self); } diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 9621c66f..c280214a 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -807,33 +807,34 @@ void FinishSpawningItem( gentity_t *ent ) { // Randomizer : after getting the item from bg_itemlist, we can finally randomize it here, because every items goes into this function and not only "gun rack" gitem_t* itemNew; + gitem_t* itemOld; // So that we have a copy of this, for debugging purpose if (cg_enableRandomizer.integer) { - // For tests prupose only + itemOld = item; + // For tests purpose only int rng = rand() % 54; itemNew = bg_itemlist + rng; - // No saber, no baton, no strange items. And no force (for now) + // No saber, no baton, no strange items. if ((strcmp(level.mapname, "yavin_trial"))) { - while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 1) || (itemNew->giTag >= 32 && itemNew->giTag <= 40) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) + while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 0) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) { rng = rand() % 53 + 1; itemNew = bg_itemlist + rng; } - // + updateItemMinsMaxs(itemNew); //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry + item = itemNew; + ent->classname == item->classname; + ent->item = item; if (itemNew->giType == IT_HOLOCRON) { - - } - else - { - item = itemNew; - updateItemMinsMaxs(item); //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry - ent->classname == item->classname; - ent->item = item; + rng = rand() % 3 + 1; + ent->item->quantity = rng; + ent->count = rng; } + } - else // Don't do anything if we are in trial, we CAN'T not get force power + else // Don't do anything if we are in trial (or other exceptions), we CAN'T not get force power { } diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp index 1f30ea61..e7a60541 100644 --- a/code/randomizer/RandomizerUtils.cpp +++ b/code/randomizer/RandomizerUtils.cpp @@ -119,7 +119,7 @@ void RandomizerInfoCommandCatcher(int page) gi.Printf(S_COLOR_MAGENTA"Here is the list of maps that have specific NPC locked :\n"); gi.Printf(S_COLOR_CYAN"Todo.\n"); break; - case 5: // + case 5: // This ISN'T true anymore, everykind of item can because any kind of items ! (Except keys and stuff on yavin_trial) gi.Printf(S_COLOR_MAGENTA"Here are the general rules for how weapons will work :\n"); gi.Printf(S_COLOR_CYAN"Weapons are replaced by other weapons (a E-11 blaster can become a bowcaster).\n"); gi.Printf(S_COLOR_CYAN"Ammo are replaced with another king of ammo. Explosives are considered ammo, so you can find them here and not in weapons slots.\n"); From 84f73e0692f6f1e35375f559caf001d9ef60812e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 8 Nov 2024 22:37:36 +0100 Subject: [PATCH 25/62] Probably the last forced NPC that we need --- code/game/NPC_spawn.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 6c318355..1673786d 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -3243,6 +3243,7 @@ bool CheckForceSpawn(gentity_t* self, char whatWeCompare[], char whoToSpawn[]) / if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); + if (strcmp(whoToSpawn, "Shadowtrooper") == 0) SP_NPC_ShadowTrooper(self); return true; // True, we forcefully spawned something } @@ -3259,6 +3260,7 @@ bool CheckForceSpawn(gentity_t* self, char whatWeCompare[], char whoToSpawn[]) / if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); + if (strcmp(whoToSpawn, "Shadowtrooper") == 0) SP_NPC_ShadowTrooper(self); return true; // True, we forcefully spawned something } @@ -3665,6 +3667,17 @@ void SP_NPC_Reborn_Random(gentity_t* self) CheckForceSpawn(self, "squad18", "Reborn"); return; } + if (strcmp(lastKnownMap, "doom_detention") == 0) // The two reborn at the end to access the jailer + { + CheckForceSpawn(self, "squad22", "Reborn"); + return; + } + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The two reborn out of the 3 kills we have to do + { + CheckForceSpawn(self, "bridge_count", "Reborn"); + CheckForceSpawn(self, "squad5", "Reborn"); + return; + } SP_NPC_Spawn_Random(self); } else SP_NPC_Reborn(self); @@ -3679,6 +3692,12 @@ void SP_NPC_ShadowTrooper_Random(gentity_t* self) SP_NPC_ShadowTrooper(self); return; } + if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The two reborn out of the 3 kills we have to do + { + CheckForceSpawn(self, "bridge_count", "Shadowtrooper"); + CheckForceSpawn(self, "squad5", "Shadowtrooper"); + return; + } SP_NPC_Spawn_Random(self); } else SP_NPC_ShadowTrooper(self); From 591c736da8dc79ea5f81f1ef36f5af967cd57568 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sat, 9 Nov 2024 00:29:32 +0000 Subject: [PATCH 26/62] Forcepowers now increment by 1 on pickup of a holocron, register holocron assets on load of ALL levels as for some reason they don't get registered by default like other items seem to. --- code/cgame/cg_main.cpp | 10 ++++++++++ code/game/Q3_Interface.cpp | 5 +++++ code/game/g_items.cpp | 22 +++++++++++++-------- code/game/wp_saber.cpp | 40 +++++++++++++++++++++++++------------- 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index c971ddaf..aa7cb2bb 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -1611,6 +1611,16 @@ static void CG_RegisterGraphics( void ) { // only register the items that the server says we need strcpy( items, CG_ConfigString( CS_ITEMS) ); + //if in randomizer, register all the holocrons + if (cg_enableRandomizer.integer) { + for (i = 1; i < bg_numItems; i++) { + if (bg_itemlist[i].giType == IT_HOLOCRON) { + CG_LoadingString(bg_itemlist[i].classname); + CG_RegisterItemVisuals(i); + } + } + } + for ( i = 1 ; i < bg_numItems ; i++ ) { if ( items[ i ] == '1' ) { diff --git a/code/game/Q3_Interface.cpp b/code/game/Q3_Interface.cpp index 566595af..14134d03 100644 --- a/code/game/Q3_Interface.cpp +++ b/code/game/Q3_Interface.cpp @@ -4057,6 +4057,11 @@ static void Q3_SetForcePowerLevel ( int entID, int forcePower, int forceLevel ) return; } + //Early exit unless we're increasing a power + if (gi.Cvar_VariableIntegerValue("cg_enableRandomizer") && forceLevel <= self->client->ps.forcePowerLevel[forcePower]) { + return; + } + if ((forceLevel > self->client->ps.forcePowerLevel[forcePower]) && (entID==0) && (forceLevel > 0)) { if (!cg_updatedDataPadForcePower1.integer) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index c280214a..c7825e42 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -379,6 +379,10 @@ int Pickup_Holocron( gentity_t *ent, gentity_t *other ) { int forcePower = ent->item->giTag; int forceLevel = ent->count; + //Always increment + if (cg_enableRandomizer.integer) { + forceLevel = other->client->ps.forcePowerLevel[forcePower] + 1; + } // check if out of range if( forceLevel < 0 || forceLevel >= NUM_FORCE_POWER_LEVELS ) { @@ -822,17 +826,19 @@ void FinishSpawningItem( gentity_t *ent ) { rng = rand() % 53 + 1; itemNew = bg_itemlist + rng; } - updateItemMinsMaxs(itemNew); //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry - item = itemNew; - ent->classname == item->classname; - ent->item = item; if (itemNew->giType == IT_HOLOCRON) { - rng = rand() % 3 + 1; - ent->item->quantity = rng; - ent->count = rng; + ent->count = 0; + } + else + { + //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry + //not for holocrons as their pickup range is pretty large already + updateItemMinsMaxs(itemNew); } - + item = itemNew; + ent->classname == item->classname; + ent->item = item; } else // Don't do anything if we are in trial (or other exceptions), we CAN'T not get force power { diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 5d925f6a..895a9bcf 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -98,6 +98,7 @@ void WP_ForcePowerDrain( gentity_t *self, forcePowers_t forcePower, int override extern cvar_t *g_saberAutoBlocking; extern cvar_t *g_saberRealisticCombat; +extern vmCvar_t cg_enableRandomizer; extern int g_crosshairEntNum; int g_saberFlashTime = 0; @@ -8598,24 +8599,35 @@ void WP_InitForcePowers( gentity_t *ent ) } else {//player - ent->client->ps.forcePowersKnown = ( 1 << FP_HEAL )|( 1 << FP_LEVITATION )|( 1 << FP_SPEED )|( 1 << FP_PUSH )|( 1 << FP_PULL )|( 1 << FP_TELEPATHY )|( 1 << FP_GRIP )|( 1 << FP_LIGHTNING)|( 1 << FP_SABERTHROW)|( 1 << FP_SABER_DEFENSE )|( 1 << FP_SABER_OFFENSE ); - ent->client->ps.forcePower = ent->client->ps.forcePowerMax = FORCE_POWER_MAX; - ent->client->ps.forcePowerRegenDebounceTime = 0; - ent->client->ps.forcePowerLevel[FP_HEAL] = FORCE_LEVEL_2; - ent->client->ps.forcePowerLevel[FP_LEVITATION] = FORCE_LEVEL_2; - ent->client->ps.forcePowerLevel[FP_PUSH] = FORCE_LEVEL_1; - ent->client->ps.forcePowerLevel[FP_PULL] = FORCE_LEVEL_1; - ent->client->ps.forcePowerLevel[FP_SABERTHROW] = FORCE_LEVEL_2; - ent->client->ps.forcePowerLevel[FP_SPEED] = FORCE_LEVEL_2; - ent->client->ps.forcePowerLevel[FP_LIGHTNING] = FORCE_LEVEL_1; - ent->client->ps.forcePowerLevel[FP_TELEPATHY] = FORCE_LEVEL_2; - ent->client->ps.forcePowerLevel[FP_SABER_DEFENSE] = FORCE_LEVEL_3; - ent->client->ps.forcePowerLevel[FP_SABER_OFFENSE] = FORCE_LEVEL_3; + //Don't initialise us with a random set of force powers please + if (cg_enableRandomizer.integer) { + ent->client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (0 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + for (int i = 0; i < NUM_FORCE_POWERS; i++) { + ent->client->ps.forcePowerLevel[i] = 0; + } + ent->client->ps.forcePowerMax = FORCE_POWER_MAX; + ent->client->ps.forcePowerRegenDebounceTime = 0; + } + else { + ent->client->ps.forcePowersKnown = (1 << FP_HEAL) | (1 << FP_LEVITATION) | (1 << FP_SPEED) | (1 << FP_PUSH) | (1 << FP_PULL) | (1 << FP_TELEPATHY) | (1 << FP_GRIP) | (1 << FP_LIGHTNING) | (1 << FP_SABERTHROW) | (1 << FP_SABER_DEFENSE) | (1 << FP_SABER_OFFENSE); + ent->client->ps.forcePower = ent->client->ps.forcePowerMax = FORCE_POWER_MAX; + ent->client->ps.forcePowerRegenDebounceTime = 0; + ent->client->ps.forcePowerLevel[FP_HEAL] = FORCE_LEVEL_2; + ent->client->ps.forcePowerLevel[FP_LEVITATION] = FORCE_LEVEL_2; + ent->client->ps.forcePowerLevel[FP_PUSH] = FORCE_LEVEL_1; + ent->client->ps.forcePowerLevel[FP_PULL] = FORCE_LEVEL_1; + ent->client->ps.forcePowerLevel[FP_SABERTHROW] = FORCE_LEVEL_2; + ent->client->ps.forcePowerLevel[FP_SPEED] = FORCE_LEVEL_2; + ent->client->ps.forcePowerLevel[FP_LIGHTNING] = FORCE_LEVEL_1; + ent->client->ps.forcePowerLevel[FP_TELEPATHY] = FORCE_LEVEL_2; + ent->client->ps.forcePowerLevel[FP_SABER_DEFENSE] = FORCE_LEVEL_3; + ent->client->ps.forcePowerLevel[FP_SABER_OFFENSE] = FORCE_LEVEL_3; + } if ( ent->NPC ) {//??? ent->client->ps.forcePowerLevel[FP_GRIP] = FORCE_LEVEL_3; } - else + else if (!cg_enableRandomizer.integer) { ent->client->ps.forcePowerLevel[FP_GRIP] = FORCE_LEVEL_2; } From 0c4680ed3991fa07812899623898bfd657c0d283 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sat, 9 Nov 2024 18:02:40 +0000 Subject: [PATCH 27/62] updated assets_randomizer.pk3 to render force holocrons correctly --- code/demo/assets_randomizer.pk3 | Bin 15222 -> 18291 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/code/demo/assets_randomizer.pk3 b/code/demo/assets_randomizer.pk3 index abcd498a4f4c25c72ceba63a0f0899ba822c2094..32f4fb8a2fddc1f0a2971868ce0ff85dd234877b 100644 GIT binary patch delta 3130 zcmb7Gc|25m8$UCM!DSfPt|g7|Vp5j6CSxhvWW6a{#kCAG7=&z(?IRHRqbB6zvz%zj0znkc;QJ74zdTb4E zs+e-Py{w!c6O(rFB0Bn#0k`mR#al0xkIu;qq0M}H({mK3IgS% ze9K>ITeCT%3H%vnX^VAdLZ&8PynOVtEjQ2`*xFNi*L(4*U6oSqQ|m>-NLLBx$nw>3 zcRAXxd9|?vLf*m|3yU1*mwDd1027%27Gdf5aPA$$XrdyQE2r8^l>Q^ex!bJ;tfo=x zLyO>M&8h)b7|GGIhsIuYX!k)Z@@;R+Q5*DYbBqRa4He*8kwMTb<03dJa+-feNjqm+ zD%J3BAxz{nv~&CtcIj4_<3;NU{KMrtT0r?5g#3SjeM2DnfY

@>?QpbK+h$T(x$KTG2;7A*{ zl7ks$BwOwzH*2aR#LjcV$Dp|taDZGn7SA1`rfDi`5<9DH}k{%{M_e8 z!9}N2WHFTe-i1hq@D``#AyP+@?@kMnfEv-*vAXvqINZe9cq|nb>LFDXE)*Y8?fI5* zJiTJ6AgrW3+%6=&Vxf3pto)-MWU~%(MS(H~YxS__`|81m;E50NCHQ)75(5mzd{{yo zA`mKkeD~n6%cAl$iGTd2o=4Ue6ttR7M2248l{Ca*zX0e)D%_pDX5V)(&hf&?jfrUe zOK=6oyXBBz56@r$!NgQ$;9*XBNcpRB2lbi(qvdXsld;D$qHIVVpIr0sewDVu+pcw! z4>V{0lJNRS7zkL)LUc9HOG|@0O8&q~&n03gq)#*CJ0s;|&!&z0#bz_<IWPVYO{&y}Dwo zr1$%74~vrfk~*Kd`NiFlQce;Vi)#1|TN80_8c@S&l>JGx!ZT(>KoitPP9MFL%1abQ3YKEN+zRTB)eKt!4bsS~lze9?`KjgJqa3=bYMc$FxG zh_f&s^?7>IK`W{~8HYe&BDqP^fDDB1@YK!hXHgBNZjtlG9!GZw!PFSIW%}ResE=qa zx?BLHV!kJQpTD=j-0r0`p3|t~AsD@&e0s98FIT$G67hLG=wLJ{?|n4%`44z`S%9WW z;^i;Xy!blvQ@INzjaekg+@)nFo{usb;$n(KhMM zE7LRMS@s}rr_iAtr=eL!MJW;&x&s4@OI{W3OVLa6Y&vqxxI@e%{+X?yPB?FgSnHLR`NR;D1{5_9bMrKLq#&iT)2f<4$ z06ZQ%yPYubd#l~@Bb{S*wWZaqcAt)(J8j3v-4KH{E^7L(XnbFJfL{hq5Y7kZ?-GO$ zTh*faFo%IiR0nlJ((ihM(!PD7qFyfigd>~-LP&d6p0_?v6C4n@jFUmU@6N6@E7z2+ zkiRVN!=ee7#5*!2+PRRgE+jEV+A66uY6MdY1N)gJy3dfYrM>n{;!k5r-pzYr;=4;_Rf{Qz6KYk9KQd=}NrTO^V;>yERmlN_-$xJ{wvXf5rItE0 zTcGN311%D$Al;pIZ<@fLihC9*k-YS++=a7*O)*H%-;|xa z5LhHuephn1_ej&H?>sFX_4$tNLKLh0ci9X{=<6)K0{y8P3w4Rg0r4c1{Ri#UU zBpWpNwWW|}mImvBuZDGl!3*qIc>w{$fiO6)Z-;t6WNWlGgFy9wRj=~34Pj5bi{X_13 Date: Sat, 9 Nov 2024 18:04:23 +0000 Subject: [PATCH 28/62] Fix build issues using FinalBuild --- code/game/game.vcxproj | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/game.vcxproj b/code/game/game.vcxproj index fc8d26ce..6ebfefd6 100644 --- a/code/game/game.vcxproj +++ b/code/game/game.vcxproj @@ -721,6 +721,7 @@ false NotUsing + NotUsing true From 8e4a22fa85d9d92f81b161eea2b05c7aaee87916 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sat, 9 Nov 2024 18:14:02 +0000 Subject: [PATCH 29/62] general repo cleanup 1 --- .gitignore | 3 + {code/demo => assets}/assets_randomizer.pk3 | Bin base/ui/ingamesetup.menu | 2994 ------------------ base/ui/setup.menu | 3105 ------------------- code/base/assets_randomizer.pk3 | Bin 15222 -> 0 bytes code/base/assets_speedoutcast.pk3.old | Bin 14545 -> 0 bytes code/base/ext_data/NPCs.cfg | 2315 -------------- code/base/ext_data/dms.dat | 1238 -------- code/base/ext_data/items.dat | 712 ----- code/base/ext_data/weapons.dat | 629 ---- code/base/jk2config.cfg | 311 -- 11 files changed, 3 insertions(+), 11304 deletions(-) rename {code/demo => assets}/assets_randomizer.pk3 (100%) delete mode 100644 base/ui/ingamesetup.menu delete mode 100644 base/ui/setup.menu delete mode 100644 code/base/assets_randomizer.pk3 delete mode 100644 code/base/assets_speedoutcast.pk3.old delete mode 100644 code/base/ext_data/NPCs.cfg delete mode 100644 code/base/ext_data/dms.dat delete mode 100644 code/base/ext_data/items.dat delete mode 100644 code/base/ext_data/weapons.dat delete mode 100644 code/base/jk2config.cfg diff --git a/.gitignore b/.gitignore index 3b0802cb..94a675de 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ **/Release **/SHDebug *vcxproj.user +*.tlog +code/base/maps/* +code/base/saves/* \ No newline at end of file diff --git a/code/demo/assets_randomizer.pk3 b/assets/assets_randomizer.pk3 similarity index 100% rename from code/demo/assets_randomizer.pk3 rename to assets/assets_randomizer.pk3 diff --git a/base/ui/ingamesetup.menu b/base/ui/ingamesetup.menu deleted file mode 100644 index d54994cd..00000000 --- a/base/ui/ingamesetup.menu +++ /dev/null @@ -1,2994 +0,0 @@ -//-------------------------------------------------------------- -// -// INGAME SETUP MENU -// -// Edited for Speed-Outcast to show speedrun options. -// -//-------------------------------------------------------------- -{ - menuDef - { - name "ingameSetupMenu" - fullScreen 1 // MENU_TRUE - rect 0 0 640 480 // Size and position of the menu - visible 1 // Visible on open - focusColor 1 1 1 1 // Focus color for text and items - appearanceIncrement 10 // In miliseconds - descX 375 - descY 425 - descScale .8 - descColor .235 .882 .847 1 // Focus color for text and items - descAlignment ITEM_ALIGN_CENTER - - onOpen - { - uiScript getvideosetup ; // Get video settings - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide defaults - hide speedrun ; - show setup_background ; - show video ; - setitemcolor video1menubutton forecolor 1 1 1 1 ; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - - onESC - { - play "sound/interface/button1.wav" - - defer VideoSetup videowarningMenu ; - - hide highlights ; - close all ; - open ingameMainMenu ; - } - - //---------------------------------------------------------------------------------------------- - // - // MENU BACKGROUND - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name frame_pic - group none - style WINDOW_STYLE_SHADER - rect 0 0 640 480 - background "gfx/menus/menu1" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - // The saber glow on the left - itemDef - { - name saberglow - group none - style WINDOW_STYLE_SHADER - rect 30 0 90 480 - background "gfx/menus/menu3" // Frame - forecolor 0.8 0.8 0.8 1 - visible 1 - decoration - } - - - // The starwars logo on the top - itemDef - { - name starwars - group none - style WINDOW_STYLE_SHADER - rect 143 12 470 93 - background "gfx/menus/menu4" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - // The saber halo on the left - itemDef - { - name saberhalo - group none - style WINDOW_STYLE_SHADER - rect -425 -185 1000 1000 - background "gfx/menus/menu2" // Frame - forecolor 0.5 0.5 0.5 1 - visible 1 - decoration - } - - itemDef - { - name logomodel - group none - type ITEM_TYPE_MODEL - rect -123 48 400 400 - model_angle 90 - model_rotation 3.5 - asset_model "models/map_objects/bespin/jk2logo.md3" -// model_fovx 37 -// model_fovy 34 -// model_origin 100 100 100 - visible 1 - decoration - } - - // The saber halo on the left - itemDef - { - name saberhalo2 - group none - style WINDOW_STYLE_SHADER - rect -225 15 600 600 - background "gfx/menus/menu2b" // Frame - forecolor 0.25 0.25 0.25 1 - visible 1 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // TOP MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - - - // Big button "SAVE" - itemDef - { - name savegamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 115 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name savegamebutton - group toprow - text @MENUS1_SAVE - descText @MENUS1_SAVE_CURRENT_GAME - style WINDOW_STYLE_EMPTY - type ITEM_TYPE_BUTTON - rect 115 115 130 24 - textaligny 0 - font 3 - textscale 0.9 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show savegamebutton_glow - } - mouseExit - { - hide savegamebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open ingamesaveMenu - } - } - - - // Big button "LOAD" - itemDef - { - name loadgamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 245 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name loadgamebutton - group toprow - text @MENUS1_LOAD - descText @MENUS1_LOAD_A_SAVED_GAME - rect 245 115 130 24 - style WINDOW_STYLE_EMPTY - type ITEM_TYPE_BUTTON - textstyle 3 - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textalignx 65 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show loadgamebutton_glow - } - mouseExit - { - hide loadgamebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open ingameloadMenu - } - } - - - // Big button "CONTROLS" - itemDef - { - name controlsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 375 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef { - name controlsbutton - group toprow - text @MENUS0_CONTROLS2 - descText @MENUS0_CONFIGURE_GAME_CONTROLS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 375 115 130 24 - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - backcolor 0 0 0 0 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show controlsbutton_glow - } - mouseExit - { - hide controlsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open ingameControlsMenu ; - } - } - - // Big button "SETUP" - itemDef - { - name setupbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 505 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef { - name setupbutton - group toprow - text @MENUS0_SETUP - descText @MENUS0_CONFIGURE_GAME_SETTINGS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 505 115 130 24 - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - backcolor 0 0 0 0 - forecolor 1 1 1 1 - visible 1 - decoration - action - { - play "sound/interface/button1.wav" ; - } - - mouseEnter - { - show setupbutton_glow - } - mouseExit - { - hide setupbutton_glow - } - } - - itemDef - { - name header_line - group toprow - style WINDOW_STYLE_SHADER - rect 125 136 500 4 - background "gfx/menus/menu_line" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // OTHER MAIN MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - // EXIT button in lower left corner - itemDef - { - name exitgamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 115 444 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name exitgamebutton - group othermain - text @MENUS0_EXIT - descText @MENUS1_JEDI_KNIGHT_II - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 115 444 130 24 - font 3 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - textaligny -1 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show exitgamebutton_glow - } - mouseExit - { - hide exitgamebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open ingamequitMenu - } - } - - // RESUME button in the lower right corner - itemDef - { - name resumebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 495 444 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name resume - group none - style WINDOW_STYLE_EMPTY - type ITEM_TYPE_BUTTON - rect 495 444 130 24 - text @MENUS1_RESUME - descText @MENUS1_RESUME_CURRENT_GAME - font 3 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - textaligny -1 - forecolor 0.65 0.65 1 1 - visible 1 - mouseEnter - { - show resumebutton_glow - } - mouseExit - { - hide resumebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - uiScript closeingame // Close menu - } - } - - //---------------------------------------------------------------------------------------------- - // - // SECOND ROW MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - // Setup Options title - itemDef - { - name setup_title - group none - style WINDOW_STYLE_SHADER - background "gfx/menus/menu_blendbox" - text @MENUS2_SETUP_OPTIONS - rect 150 145 450 16 - font 3 - textscale 0.7 - textalign ITEM_ALIGN_CENTER - textalignx 225 - textaligny -2 - forecolor 1 1 1 1 - visible 1 - // appearance_slot 2 - decoration - } - - - // video1 button - itemDef - { - name video1button_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 173 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name video1menubutton - group none - text @MENUS1_VIDEO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 173 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textstyle 3 - textalign ITEM_ALIGN_RIGHT - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_VIDEO_SETTINGS - - mouseEnter - { - show video1button_glow - } - mouseExit - { - hide video1button_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - uiScript getvideosetup ; // Get video settings - - show setup_background ; - show video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide defaults ; - hide speedrun ; - setfocus graphics ; - setitemcolor video1menubutton forecolor 1 1 1 1 ; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // video2 button - itemDef - { - name video2button_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 203 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name video2menubutton - group none - text @MENUS1_MORE_VIDEO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 203 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGUE_MORE_VIDEO_SETTINGS - - mouseEnter - { - show video2button_glow - } - mouseExit - { - hide video2button_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - show video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor video2menubutton forecolor 1 1 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1 ; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1 ; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // sound button - itemDef - { - name soundbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 233 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name soundmenubutton - group none - text @MENUS1_SOUND - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 233 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_SOUND_SETTINGS - - mouseEnter - { - show soundbutton_glow - } - mouseExit - { - hide soundbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - show sound ; - hide options ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 1 1 1 1 ; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // gameoptions button - itemDef - { - name gameoptionsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 263 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name gameoptionmenubutton - group none - text @MENUS1_GAME_OPTIONS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 263 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_GAME_OPTIONS - - mouseEnter - { - show gameoptionsbutton_glow - } - mouseExit - { - hide gameoptionsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - show options ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 1 1 1 1 ; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - - // gamedefaults button - itemDef - { - name gamedefaultsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 323 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name gamedefaultsmenubutton - group none - text @MENUS1_DEFAULTS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 323 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_RESTORE_DEFAULT_SETTINGS - - mouseEnter - { - show gamedefaultsbutton_glow - } - mouseExit - { - hide gamedefaultsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - show defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 1 1 1 1 ; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // speedrun button - itemDef - { - name speedrunmenubutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 368 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name speedrunmenubutton - group none - text Speedrun - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 368 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText "Speedrun Settings" - - mouseEnter - { - show speedrunmenubutton_glow - } - mouseExit - { - hide speedrunmenubutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide defaults ; - show speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 1 1 1 1 ; - } - } - - itemDef - { - name setup_background - group none - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_box1" // Frame - forecolor 1 1 1 1 - visible 0 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // HIGHLIGHT BARS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name highlight1 - group highlights - style WINDOW_STYLE_SHADER - rect 305 171 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight2 - group highlights - style WINDOW_STYLE_SHADER - rect 305 191 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight3 - group highlights - style WINDOW_STYLE_SHADER - rect 305 211 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight4 - group highlights - style WINDOW_STYLE_SHADER - rect 305 231 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight5 - group highlights - style WINDOW_STYLE_SHADER - rect 305 251 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight6 - group highlights - style WINDOW_STYLE_SHADER - rect 305 271 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight7 - group highlights - style WINDOW_STYLE_SHADER - rect 305 291 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight8 - group highlights - style WINDOW_STYLE_SHADER - rect 305 311 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight9 - group highlights - style WINDOW_STYLE_SHADER - rect 305 331 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight10 - group highlights - style WINDOW_STYLE_SHADER - rect 305 351 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight11 - group highlights - style WINDOW_STYLE_SHADER - rect 305 371 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight12 - group highlights - style WINDOW_STYLE_SHADER - rect 305 391 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // VIDEO 1 MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name graphics - group video - text @MENUS0_VIDEO_QUALITY - type ITEM_TYPE_MULTI - rect 305 171 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - style WINDOW_STYLE_FILLED - forecolor 1 1 1 1 - descText @MENUS1_SELECT_PRESET_GRAPHIC - - visible 0 - - cvar "ui_r_glCustom" - cvarFloatList - { - @MENUS1_HIGH_QUALITY 0 - @MENUS1_NORMAL 1 - @MENUS1_FAST 2 - @MENUS1_FASTEST 3 - @MENUS1_CUSTOM 4 - } - - mouseenter - { - show highlight1 - } - mouseexit - { - hide highlight1 - } - action - { - play "sound/interface/button1.wav" ; - uiScript update "ui_r_glCustom" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - - itemDef - { - name video_mode - group video - type ITEM_TYPE_MULTI - text @MENUS0_VIDEO_MODE - cvarFloatList { @MENUS1_640_X_480 3 @MENUS1_800_X_600 4 @MENUS1_960_X_720 5 @MENUS1_1024_X_768 6 @MENUS1_1152_X_864 7 @MENUS1_1280_X_1024 8 @MENUS1_1600_X_1200 9 @MENUS1_2048_X_1536 10 } - cvar "ui_r_mode" - - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - descText @MENUS1_CHANGE_THE_DISPLAY_RESOLUTION - - visible 0 - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name color_depth - group video - type ITEM_TYPE_MULTI - text @MENUS0_COLOR_DEPTH - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - - cvarFloatList { @MENUS0_DEFAULT 0 @MENUS0_16_BIT 16 @MENUS0_32_BIT 32 } - descText @MENUS1_CHANGE_THE_NUMBER_OF - cvar "ui_r_colorbits" - - visible 0 - - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - uiScript update "ui_r_colorbits" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name fullscreen - group video - type ITEM_TYPE_MULTI - text @MENUS0_FULL_SCREEN - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_TOGGLE_BETWEEN_FULL_SCREEN - cvar "ui_r_fullscreen" - - visible 0 - - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name geometric_detail - group video - type ITEM_TYPE_MULTI - text @MENUS0_GEOMETRIC_DETAIL - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_LOW 2 @MENUS0_MEDIUM 1 @MENUS0_HIGH 0 } - descText @MENUS1_ADJUST_THE_NUMBER_OF - cvar "ui_r_lodbias" - - visible 0 - - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - uiScript update "ui_r_lodbias" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_detail - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_DETAIL - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_LOW 3 @MENUS0_MEDIUM 2 @MENUS0_HIGH 1 @MENUS0_VERY_HIGH 0 } - descText @MENUS1_SELECT_THE_RESOLUTION - cvar "ui_r_picmip" - - visible 0 - - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_quality - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_QUALITY - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_DEFAULT 0 @MENUS0_16_BIT 16 @MENUS0_32_BIT 32 } - descText @MENUS1_SELECT_THE_NUMBER_OF - cvar "ui_r_texturebits" - - visible 0 - - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_filter - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_FILTER - rect 305 331 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarStrList { @MENUS1_BILINEAR , "GL_LINEAR_MIPMAP_NEAREST" , @MENUS1_TRILINEAR , "GL_LINEAR_MIPMAP_LINEAR" } - descText @MENUS1_ADJUST_HOW_WELL_THE_TEXTURES - cvar "ui_r_texturemode" - - visible 0 - - mouseenter - { - show highlight9 - } - mouseexit - { - hide highlight9 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name simple_shaders - group video - type ITEM_TYPE_MULTI - text @MENUS0_DETAILED_SHADERS - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_HIDE_OR_UNHIDE_TEXTURES - cvar "ui_r_detailtextures" - - visible 0 - - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name compress_textures - group video_obsolete - type ITEM_TYPE_MULTI - text @MENUS0_COMPRESSED_TEXTURES - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_TAKE_ADVANTAGE_OF_3D - cvar "ui_r_ext_compress_textures" - - visible 0 - - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - // APPLY CHANGES BUTTON - itemDef - { - name applybutton_glow - group none - style WINDOW_STYLE_SHADER - rect 120 383 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 0.5 0.5 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name applyChanges - group none - text @MENUS0_APPLY_CHANGES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 383 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 1 0 0 1 - backcolor 0 0 1 0 - visible 0 - - mouseEnter - { - show applybutton_glow - } - mouseExit - { - hide applybutton_glow - } - action - { - play "sound/interface/button1.wav" ; - show setup_background ; - show vidrestart ; - setfocus vidrestart_no ; - hide video ; - hide video2 ; - hide applybutton_glow ; - } - } - - -// This button doesn't get shown anymore. - itemDef - { - name gl_extensions - group video - type ITEM_TYPE_MULTI - text @MENUS1_GL_EXTENSIONS - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - cvar ui_r_allowExtensions - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - // appearance_slot 3 - descText @MENUS2_TOGGLE_GL_EXTENSIONS - - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - action - { - play "sound/interface/button1.wav" - setcvar ui_r_modified 1 - show applyChanges - } - } - - - //---------------------------------------------------------------------------------------------- - // - // VIDEO RESTART - // - //---------------------------------------------------------------------------------------------- - // Faint red box - itemDef - { - name vidrestart_background - group vidrestart - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_boxred" // Frame - forecolor 1 1 1 0.5 - visible 0 - decoration - } - - itemDef - { - name vidrestart_text1 - group vidrestart - text @MENUS3_INGAME_DEFAULT - text2 @MENUS3_INGAME_DEFAULT2 - rect 305 230 290 20 - textalign ITEM_ALIGN_CENTER - text2aligny 18 - textalignx 145 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name vidrestart_text2 - group vidrestart - text @MENUS0_VID_RESTART3 - rect 305 300 290 20 - textalign ITEM_ALIGN_CENTER - textalignx 145 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - } - - - - itemDef - { - name vidrestart_yes_button - group none - style WINDOW_STYLE_SHADER - rect 467 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 4 - } - - // YES button - itemDef - { - name vidrestart_yes - group vidrestart - text @MENUS0_YES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 467 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textalignx 60 - textaligny 0 - descText @MENUS0_APPLY_CHANGES_AND_THEN - forecolor 0.65 0.65 1 1 - visible -1 - // appearance_slot 5 - - action - { - play "sound/interface/button1.wav" ; - close all ; - uiScript updatevideosetup ; - } - mouseEnter - { - show vidrestart_yes_button - } - mouseExit - { - hide vidrestart_yes_button - } - - } - - itemDef - { - name vidrestart_no_button - group none - style WINDOW_STYLE_SHADER - rect 305 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 3 - } - - // CANCEL button - itemDef - { - name vidrestart_no - group vidrestart - text @MENUS0_NO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 305 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textalignx 60 - textaligny -1 - descText @MENUS0_DO_NOT_APPLY_CHANGES - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 6 - action - { - play "sound/interface/button1.wav" ; - setfocus video1menubutton ; - show setup_background ; - hide vidrestart ; - show video ; - hide video2 ; - show applyChanges ; - hide vidrestart_yes_button ; - hide vidrestart_no_button ; - } - mouseEnter - { - show vidrestart_no_button - } - mouseExit - { - hide vidrestart_no_button - } - - } - - //---------------------------------------------------------------------------------------------- - // - // VIDEO 2 - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name gamma_text - group video2 - style WINDOW_STYLE_SHADER - rect 310 171 280 36 - background "gfx/menus/greyscale" // greyscale - forecolor 1 1 1 1 - visible 0 - decoration - // appearance_slot 1 - } - - - - itemDef - { - name bright_text - group video2 - text @MENUS0_ADJUST_BRIGHTNESS_SLIDER - text2 @MENUS0_THE_NUMBER_6_CAN_BARELY - text2aligny 14 - textalignx 128 - font 2 - textscale 0.8 - rect 305 211 256 20 - textalign ITEM_ALIGN_CENTER - forecolor 0.7 0.7 0.7 1 - visible 0 - // appearance_slot 2 - decoration - } - - itemDef - { - name brightness - group video2 - type ITEM_TYPE_SLIDER - text @MENUS0_VIDEO_BRIGHTNESS - cvarfloat "r_gamma" 1 .5 3 - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 3 - descText @MENUS1_ADJUST_THE_BRIGHTNESS - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - } - - itemDef - { - name video_sync - group video2 - type ITEM_TYPE_MULTI - text @MENUS3_VIDEO_SYNC - cvar "r_swapInterval" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_VIDEO_SYNC_DESC - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - } - - - - itemDef - { - name dynamic_light - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_DYNAMIC_LIGHTS - cvar "r_dynamiclight" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_TURN_ON_MOVING - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - } - - itemDef - { - name shadows - group video2 - type ITEM_TYPE_MULTI - text @MENUS3_SHADOWS - descText @MENUS3_SHADOWS_DESC - cvar "cg_shadows" - cvarFloatList - { - "None" 0 - "Simple" 1 - "Volumetric" 2 -// "Projected" 3 - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } - - itemDef - { - name wall_marks - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_WALL_MARKS - cvar "cg_marks" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 331 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_DISPLAY_SCORCH - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight9 - } - mouseexit - { - hide highlight9 - } - } - - itemDef - { - name video_mode - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_ANISOTROPIC_FILTERING - cvarTest r_ext_texture_filter_anisotropic_avail - hideCvar { 0 } - cvar r_ext_texture_filter_anisotropic - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 5 - - descText @MENUS1_TOGGLE_ADVANCED_TEXTURE - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - } - - itemDef - { - name light_flares - group video2_obsolete - type ITEM_TYPE_MULTI - text @MENUS0_LIGHT_FLARES - cvar "r_flares" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_SHOW_HALOS - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - } - - itemDef - { - name advancedvideobutton_glow - group none - style WINDOW_STYLE_SHADER - rect 355 391 200 20 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name advancedvideo - group video2 - type ITEM_TYPE_BUTTON - text @MENUS2_SHOW_DRIVER_INFO - rect 355 391 200 20 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 100 - font 2 - textscale 0.8 - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 5 - descText @MENUS2_SHOW_ADVANCED_INFORMATION - - mouseenter - { - show advancedvideobutton_glow - } - mouseexit - { - hide advancedvideobutton_glow - } - action - { - play "sound/interface/button1.wav" ; - hide advancedvideobutton_glow ; - open videodriverMenu - } - } - - //---------------------------------------------------------------------------------------------- - // - // SOUND FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name effects_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS0_EFFECTS_VOLUME - cvarfloat "s_volume" 0 0 1 - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_ADJUST_VOLUME_FOR_SOUND - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - itemDef - { - name music_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS0_MUSIC_VOLUME - cvarfloat "s_musicvolume" 0 0 1 - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 2 - descText @MENUS1_ADJUST_VOLUME_FOR_MUSIC - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - itemDef - { - name voice_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS1_VOICE_VOLUME - cvarfloat "s_volumevoice" 0 0 1 - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 2 - descText @MENUS2_ADJUST_VOLUME_FOR_SPEECH - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - itemDef - { - name sound_quality - group sound - type ITEM_TYPE_MULTI - text @MENUS0_SOUND_QUALITY - cvar "s_khz" - cvarFloatList { @MENUS0_LOW 11 @MENUS0_HIGH 22 } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 3 - descText @MENUS2_TRADE_CLARITY_OF_SOUND - - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - action - { - play "sound/interface/button1.wav" - uiScript update s_khz - } - } - - //---------------------------------------------------------------------------------------------- - // - // OPTION FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name draw_crosshair - group options - type ITEM_TYPE_MULTI - text @MENUS2_DRAW_CROSSHAIR - cvar "cg_drawcrosshair" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 171 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_TOGGLE_TO_SHOW_OR_HIDE - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight1 - } - mouseexit - { - hide highlight1 - } - } - - - itemDef - { - name identifytarget - group options - type ITEM_TYPE_MULTI - text @MENUS0_IDENTIFY_TARGET - cvar "cg_crosshairIdentifyTarget" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_TOGGLE_TO_HAVE_THE_CROSSHAIR - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - - itemDef - { - name slowmo - group options - type ITEM_TYPE_MULTI - text @MENUS2_SLOW_MOTION_DEATH - cvar "d_slowmodeath" - cvarFloatList - { - @MENUS2_NEVER 0 - @MENUS2_ON_DEATH 1 - @MENUS2_RARELY 2 - @MENUS1_NORMAL 3 - @MENUS2_OFTEN 4 - @MENUS2_FREQUENTLY 5 - @MENUS2_EXCESSIVELY 6 - } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_THE_FREQUENCY - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - - itemDef - { - name force3rd - group options - type ITEM_TYPE_MULTI - text @MENUS2_3RD_PERSON_LIGHTSABER - cvar "cg_saberAutoThird" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_WHEN_READYING_LIGHTSABER - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - - itemDef - { - name force1st - group options - type ITEM_TYPE_MULTI - text @MENUS2_1ST_PERSON_GUNS - cvar "cg_gunAutoFirst" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_WHEN_PUTTING_AWAY_SABER - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - } - - - itemDef - { - name dismemberment - group options - type ITEM_TYPE_MULTI - text @MENUS2_DISMEMBERMENT - cvar "g_dismemberment" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 3 - } - cvarTest ui_iscensored - hideCvar { 1 } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_WHAT_LIGHTSABER - action - { - play "sound/interface/button1.wav" ; - } - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - } - - -// Weapon Sway. Yes, this is nutty. Two cvars here, one removes weapon sway, the other adds it. - itemDef - { - name weaponswayon - group options - type ITEM_TYPE_MULTI - text @MENUS3_VIEW_SWAYING - descText @MENUS3_VIEW_SWAYING_DESC - cvar "ui_disableWeaponSway" - cvarFloatList - { - @MENUS0_ON 0 - @MENUS0_OFF 1 - } - cvarTest "ui_disableWeaponSway" - showCvar - { - "0" - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - - action - { - play "sound/interface/button1.wav" ; - exec "exec noMotion.cfg" ; - show weaponswayoff ; - setfocus weaponswayoff - } - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } - - itemDef - { - name weaponswayoff - group options - type ITEM_TYPE_MULTI - text @MENUS3_VIEW_SWAYING - descText @MENUS3_VIEW_SWAYING_DESC - cvar "ui_disableWeaponSway" - cvarFloatList - { - @MENUS0_ON 0 - @MENUS0_OFF 1 - } - cvarTest "ui_disableWeaponSway" - hideCvar - { - "0" - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - - action - { - play "sound/interface/button1.wav" ; - exec "exec restoreMotion.cfg" ; - show weaponswayon ; - setfocus weaponswayon - } - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } - -/* - itemDef - { - name dismembermentprob - group options_obsolete - type ITEM_TYPE_MULTI - text @MENUS2_DISMEMBER_PROBABILITY - cvar "g_dismemberProbabilities" - cvarFloatList - { - @MENUS2_RARE 2 - @MENUS1_NORMAL 1 - @MENUS2_EXCESSIVE 0 - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_FREQUENCY_OF_DISMEMBERMENT - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } -*/ - - itemDef - { - name text - group options - type ITEM_TYPE_MULTI - text @MENUS0_TEXT - cvar "sp_language" - cvarFloatList - { - "English" 0 - "Francais" 1 - "Deutsch" 2 - } - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_CHOOSE_THE_LANGUAGE_FOR - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - } - - itemDef - { - name voice - group options - type ITEM_TYPE_MULTI - text @MENUS1_VOICE - cvar "s_language" - cvarStrList - { - "English", "english" - "Francais" "francais" - "Deutsch" "deutsch" - } - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_CHOOSE_THE_LANGUAGE_TO - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - } - - itemDef - { - name voice - group options - type ITEM_TYPE_MULTI - text @MENUS1_SUBTITLES - cvar "g_subtitles" - cvarFloatList - { - @MENUS3_NONE 0 - @MENUS3_IN_CINEMATICS 2 -// @MENUS3_ALL_VOICEOVERS 1 - } - rect 305 391 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_TOGGLE_WHETHER_SUBTITLES - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight12 - } - mouseexit - { - hide highlight12 - } - } - - - -// This menu option is no longer used. - itemDef - { - name sync_frame - group options_obsolete - type ITEM_TYPE_MULTI - text @MENUS1_SYNC_EVERY_FRAME - cvar "r_finish" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 1 - } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_TOGGLE_TO_PREVENT_VIDEO - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - - //---------------------------------------------------------------------------------------------- - // - // RESET DEFAULTS - // - //---------------------------------------------------------------------------------------------- - // Faint red box - itemDef - { - name vidrestart_background - group defaults - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_boxred" // Frame - forecolor 1 1 1 0.5 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS0_WARNING - rect 305 191 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS3_INGAME_DEFAULT - text2 @MENUS3_INGAME_DEFAULT2 - rect 305 231 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - text2aligny 20 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS0_VID_RESTART3 - rect 305 291 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - - itemDef - { - name default_yes_button - group highlights - style WINDOW_STYLE_SHADER - rect 467 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 4 - } - - // YES button - lose reset defaults - itemDef - { - name default_yes - group defaults - text @MENUS0_YES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 467 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 60 - textaligny 0 - descText @MENUS1_RESET_DEFAULT_VALUES - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 5 - - action - { - play "sound/interface/button1.wav" ; - hide highlights ; - close all ; - uiscript resetdefaults - } - mouseEnter - { - show default_yes_button - } - mouseExit - { - hide default_yes_button - } - - } - - itemDef - { - name default_no_button - group highlights - style WINDOW_STYLE_SHADER - rect 305 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 3 - } - - // NO button - return to Main Menu - itemDef - { - name default_no - group defaults - text @MENUS0_NO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 305 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 60 - textaligny 0 - descText @MENUS1_NOT_RESET_DEFAULT_VALUES - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 6 - action - { - play "sound/interface/button1.wav" ; - hide highlights ; - close all ; - open ingameMainMenu ; - } - mouseEnter - { - show default_no_button - } - mouseExit - { - hide default_no_button - } - } - - //---------------------------------------------------------------------------------------------- - // - // SPEEDRUN FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name draw_secrets - group speedrun - type ITEM_TYPE_MULTI - text "Show Secret Count:" - cvar "cg_drawSecrets" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText "Toggle to show number of found and total secrets." - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - - itemDef - { - name draw_overbounceinfo - group speedrun - type ITEM_TYPE_MULTI - text "Show Overbounce Info:" - cvar "cg_drawOverbounceInfo" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText "Toggle to show or hide overbounce information." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - - itemDef - { - name draw_speed - group speedrun - type ITEM_TYPE_MULTI - text "Show Speed:" - cvar "cg_drawSpeed" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide speed display." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - - itemDef - { - name draw_strafehelper - group speedrun - type ITEM_TYPE_MULTI - text "Strafe Helper:" - cvar "cg_drawStrafeHelper" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide the strafe helper." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - } - - - itemDef - { - name draw_jumphelper - group speedrun - type ITEM_TYPE_MULTI - text "Jump Height Helper:" - cvar "cg_drawJumpHelper" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide the jump height helper." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - } - } -} diff --git a/base/ui/setup.menu b/base/ui/setup.menu deleted file mode 100644 index fac73c08..00000000 --- a/base/ui/setup.menu +++ /dev/null @@ -1,3105 +0,0 @@ -//-------------------------------------------------------------- -// -// SETUP MENU -// -// Edited for Speed-Outcast to show speedrun options. -// -//-------------------------------------------------------------- -{ - menuDef - { - name "setupMenu" - fullScreen 1 // MENU_TRUE - rect 0 0 640 480 // Size and position of the menu - visible 1 // Visible on open - focusColor 1 1 1 1 // Focus color for text and items - background "gfx/menus/mainback" // Frame - appearanceIncrement 75 // In miliseconds - descX 375 - descY 425 - descScale .8 - descColor .235 .882 .847 1 // Focus color for text and items - descAlignment ITEM_ALIGN_CENTER - - onOpen - { - uiScript getvideosetup ; // Get video settings - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide mods ; - hide defaults ; - hide speedrun ; - show video ; - show setup_background ; - hide highlights ; - setitemcolor video1menubutton forecolor 1 1 1 1 ; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - - onESC - { - play "sound/interface/button1.wav" - - defer VideoSetup videowarningMenu ; - - close all ; - open mainMenu - } - - //---------------------------------------------------------------------------------------------- - // - // MENU BACKGROUND - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name frame_pic - group none - style WINDOW_STYLE_SHADER - rect 0 0 640 480 - background "gfx/menus/menu1" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - // The saber glow on the left - itemDef - { - name saberglow - group none - style WINDOW_STYLE_SHADER - rect 30 0 90 480 - background "gfx/menus/menu3" // Frame - forecolor 0.8 0.8 0.8 1 - visible 1 - decoration - } - - - // The starwars logo on the top - itemDef - { - name starwars - group none - style WINDOW_STYLE_SHADER - rect 143 12 470 93 - background "gfx/menus/menu4" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - // The saber halo on the left - itemDef - { - name saberhalo - group none - style WINDOW_STYLE_SHADER - rect -425 -185 1000 1000 - background "gfx/menus/menu2" // Frame - forecolor 0.5 0.5 0.5 1 - visible 1 - decoration - } - - itemDef - { - name logomodel - group none - type ITEM_TYPE_MODEL - rect -123 48 400 400 - model_angle 90 - model_rotation 3.5 - asset_model "models/map_objects/bespin/jk2logo.md3" -// model_fovx 37 -// model_fovy 34 -// model_origin 100 100 100 - visible 1 - decoration - } - - // The saber halo on the left - itemDef - { - name saberhalo2 - group none - style WINDOW_STYLE_SHADER - rect -225 15 600 600 - background "gfx/menus/menu2b" // Frame - forecolor 0.25 0.25 0.25 1 - visible 1 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // TOP MAIN MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - - // Big button "NEW" - itemDef - { - name newgamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 115 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name newgamebutton - group toprow - style WINDOW_STYLE_EMPTY - type ITEM_TYPE_BUTTON - rect 115 115 130 24 - text @MENUS1_NEW - descText @MENUS1_START_A_NEW_GAME - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textalignx 65 - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show newgamebutton_glow - } - mouseExit - { - hide newgamebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open newgameMenu - } - } - - // Big button "LOAD" - itemDef - { - name loadgamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 245 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name loadgamebutton - group toprow - text @MENUS1_LOAD - descText @MENUS1_LOAD_A_SAVED_GAME - style WINDOW_STYLE_EMPTY - type ITEM_TYPE_BUTTON - rect 245 115 130 24 - textaligny 0 - font 3 - textscale 0.9 - textalign ITEM_ALIGN_CENTER - textalignx 65 - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show loadgamebutton_glow - } - mouseExit - { - hide loadgamebutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open loadgameMenu - } - } - - // Big button "CONTROLS" - itemDef - { - name controlsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 375 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef { - name controlsbutton - group toprow - text @MENUS0_CONTROLS2 - descText @MENUS0_CONFIGURE_GAME_CONTROLS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 375 115 130 24 - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - backcolor 0 0 0 0 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show controlsbutton_glow - } - mouseExit - { - hide controlsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open controlsMenu ; - } - - } - - // Big button "SETUP" - itemDef - { - name setupbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 505 115 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef { - name setupbutton - group toprow - text @MENUS0_SETUP - descText @MENUS0_CONFIGURE_GAME_SETTINGS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 505 115 130 24 - font 3 - textscale 0.9 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - backcolor 0 0 0 0 - forecolor 1 1 1 1 - visible 1 - decoration - action - { - play "sound/interface/button1.wav" ; - } - - - mouseEnter - { - show setupbutton_glow - } - mouseExit - { - hide setupbutton_glow - } - } - - itemDef - { - name header_line - group toprow - style WINDOW_STYLE_SHADER - rect 125 136 500 4 - background "gfx/menus/menu_line" // Frame - forecolor 1 1 1 1 - visible 1 - decoration - } - - - //---------------------------------------------------------------------------------------------- - // - // OTHER MAIN MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - // Credits hidden button - itemDef - { - name creditsbutton - group othermain -// text @CREDITS - descText @MENUS0_SHOW_GAME_CREDITS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 51 284 52 60 - font 2 - textscale 1 - textaligny 0 - textalign ITEM_ALIGN_CENTER - textalignx 46 - backcolor 0 0 0 0 - forecolor 0.65 0.65 1 1 - visible 0 - - mouseEnter - { - setitemcolor saberhalo2 forecolor 0.7 0.7 0.7 1 - } - mouseExit - { - setitemcolor saberhalo2 forecolor 0.25 0.25 0.25 1 - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - close all ; - open creditsMenu - } - } - - // EXIT button in lower left corner - // Big button "SETUP" - itemDef - { - name exitgamebutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 115 444 130 24 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name exitgamebutton - group othermain - text @MENUS0_EXIT - descText @MENUS1_JEDI_KNIGHT_II - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 115 444 130 24 - font 3 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 65 - textaligny -1 - forecolor 0.65 0.65 1 1 - visible 1 - - mouseEnter - { - show exitgamebutton_glow - } - mouseExit - { - hide exitgamebutton_glow - } - action - { - play "sound/weapons/saber/saberoff.mp3"; - - defer VideoSetup videowarningMenu ; - - close all ; - open quitMenu - } - } - - //---------------------------------------------------------------------------------------------- - // - // SECOND ROW MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - // Setup Options title - itemDef - { - name setup_title - group none - style WINDOW_STYLE_SHADER - background "gfx/menus/menu_blendbox" - text @MENUS2_SETUP_OPTIONS - rect 150 145 450 16 - font 3 - textscale 0.7 - textalign ITEM_ALIGN_CENTER - textalignx 225 - textaligny -2 - forecolor 1 1 1 1 - visible 1 - // appearance_slot 2 - decoration - } - - - // video1 button - itemDef - { - name video1button_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 173 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name video1menubutton - group none - text @MENUS1_VIDEO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 173 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textstyle 3 - textalign ITEM_ALIGN_RIGHT - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_VIDEO_SETTINGS - - mouseEnter - { - show video1button_glow - } - mouseExit - { - hide video1button_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - uiScript getvideosetup ; // Get video settings - - show setup_background ; - show video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide mods ; - hide defaults ; - hide speedrun ; - setfocus graphics ; - setitemcolor video1menubutton forecolor 1 1 1 1 ; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // video2 button - itemDef - { - name video2button_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 203 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name video2menubutton - group none - text @MENUS1_MORE_VIDEO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 203 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGUE_MORE_VIDEO_SETTINGS - - mouseEnter - { - show video2button_glow - } - mouseExit - { - hide video2button_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - show video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide mods ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1 ; - setitemcolor video2menubutton forecolor 1 1 1 1 ; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1 ; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1 ; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // sound button - itemDef - { - name soundbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 233 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name soundmenubutton - group none - text @MENUS1_SOUND - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 233 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_SOUND_SETTINGS - - mouseEnter - { - show soundbutton_glow - } - mouseExit - { - hide soundbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - show sound ; - hide options ; - hide mods ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 1 1 1 1 ; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // gameoptions button - itemDef - { - name gameoptionsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 263 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name gameoptionmenubutton - group none - text @MENUS1_GAME_OPTIONS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 263 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_GAME_OPTIONS - - mouseEnter - { - show gameoptionsbutton_glow - } - mouseExit - { - hide gameoptionsbutton_glow - } - action - { - defer VideoSetup videowarningMenu ; - - play "sound/interface/button1.wav" ; - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - show options ; - hide mods ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 1 1 1 1 ; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // mods button - itemDef - { - name modsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 293 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name modsmenubutton - group none - text @MENUS1_MODS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 293 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_CONFIGURE_GAME_OPTIONS - - mouseEnter - { - show modsbutton_glow - } - mouseExit - { - hide modsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - show mods ; - hide defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 1 1 1 1 ; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // gamedefaults button - itemDef - { - name gamedefaultsbutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 323 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name gamedefaultsmenubutton - group none - text @MENUS1_DEFAULTS - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 323 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText @MENUS0_RESTORE_DEFAULT_SETTINGS - - mouseEnter - { - show gamedefaultsbutton_glow - } - mouseExit - { - hide gamedefaultsbutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide mods ; - show defaults ; - hide speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 1 1 1 1 ; - setitemcolor speedrunmenubutton forecolor 0.65 0.65 1 1; - } - } - - // speedrun button - itemDef - { - name speedrunmenubutton_glow - group highlights - style WINDOW_STYLE_SHADER - rect 120 368 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name speedrunmenubutton - group none - text Speedrun - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 368 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 0.65 0.65 1 1 - visible 1 - descText "Speedrun Settings" - - mouseEnter - { - show speedrunmenubutton_glow - } - mouseExit - { - hide speedrunmenubutton_glow - } - action - { - play "sound/interface/button1.wav" ; - - defer VideoSetup videowarningMenu ; - - show setup_background ; - hide video ; - hide applyChanges ; - hide video2 ; - hide vidrestart ; - hide sound ; - hide options ; - hide mods ; - hide defaults ; - show speedrun ; - setitemcolor video1menubutton forecolor 0.65 0.65 1 1; - setitemcolor video2menubutton forecolor 0.65 0.65 1 1; - setitemcolor soundmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gameoptionmenubutton forecolor 0.65 0.65 1 1; - setitemcolor modsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor gamedefaultsmenubutton forecolor 0.65 0.65 1 1; - setitemcolor speedrunmenubutton forecolor 1 1 1 1 ; - } - } - - itemDef - { - name setup_background - group none - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_box1" // Frame - forecolor 1 1 1 1 - visible 0 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // HIGHLIGHT BARS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name highlight1 - group highlights - style WINDOW_STYLE_SHADER - rect 305 171 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight2 - group highlights - style WINDOW_STYLE_SHADER - rect 305 191 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight3 - group highlights - style WINDOW_STYLE_SHADER - rect 305 211 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight4 - group highlights - style WINDOW_STYLE_SHADER - rect 305 231 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight5 - group highlights - style WINDOW_STYLE_SHADER - rect 305 251 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight6 - group highlights - style WINDOW_STYLE_SHADER - rect 305 271 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight7 - group highlights - style WINDOW_STYLE_SHADER - rect 305 291 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight8 - group highlights - style WINDOW_STYLE_SHADER - rect 305 311 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight9 - group highlights - style WINDOW_STYLE_SHADER - rect 305 331 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight10 - group highlights - style WINDOW_STYLE_SHADER - rect 305 351 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight11 - group highlights - style WINDOW_STYLE_SHADER - rect 305 371 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - itemDef - { - name highlight12 - group highlights - style WINDOW_STYLE_SHADER - rect 305 391 300 20 - background "gfx/menus/menu_blendbox" - forecolor 1 1 1 1 - visible 0 - decoration - } - - //---------------------------------------------------------------------------------------------- - // - // VIDEO 1 MENU BUTTONS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name graphics - group video - text @MENUS0_VIDEO_QUALITY - type ITEM_TYPE_MULTI - rect 305 171 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - style WINDOW_STYLE_FILLED - forecolor 1 1 1 1 - descText @MENUS1_SELECT_PRESET_GRAPHIC - - visible 0 - - cvar "ui_r_glCustom" - cvarFloatList - { - @MENUS1_HIGH_QUALITY 0 - @MENUS1_NORMAL 1 - @MENUS1_FAST 2 - @MENUS1_FASTEST 3 - @MENUS1_CUSTOM 4 - } - - mouseenter - { - show highlight1 - } - mouseexit - { - hide highlight1 - } - action - { - play "sound/interface/button1.wav" ; - uiScript update "ui_r_glCustom" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - - itemDef - { - name video_mode - group video - type ITEM_TYPE_MULTI - text @MENUS0_VIDEO_MODE - cvarFloatList { @MENUS1_640_X_480 3 @MENUS1_800_X_600 4 @MENUS1_960_X_720 5 @MENUS1_1024_X_768 6 @MENUS1_1152_X_864 7 @MENUS1_1280_X_1024 8 @MENUS1_1600_X_1200 9 @MENUS1_2048_X_1536 10 } - cvar "ui_r_mode" - - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - descText @MENUS1_CHANGE_THE_DISPLAY_RESOLUTION - - visible 0 - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name color_depth - group video - type ITEM_TYPE_MULTI - text @MENUS0_COLOR_DEPTH - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - - cvarFloatList { @MENUS0_DEFAULT 0 @MENUS0_16_BIT 16 @MENUS0_32_BIT 32 } - descText @MENUS1_CHANGE_THE_NUMBER_OF - cvar "ui_r_colorbits" - - visible 0 - - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - uiScript update "ui_r_colorbits" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name fullscreen - group video - type ITEM_TYPE_MULTI - text @MENUS0_FULL_SCREEN - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_TOGGLE_BETWEEN_FULL_SCREEN - cvar "ui_r_fullscreen" - - visible 0 - - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name geometric_detail - group video - type ITEM_TYPE_MULTI - text @MENUS0_GEOMETRIC_DETAIL - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_LOW 2 @MENUS0_MEDIUM 1 @MENUS0_HIGH 0 } - descText @MENUS1_ADJUST_THE_NUMBER_OF - cvar "ui_r_lodbias" - - visible 0 - - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - uiScript update "ui_r_lodbias" ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_detail - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_DETAIL - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_LOW 3 @MENUS0_MEDIUM 2 @MENUS0_HIGH 1 @MENUS0_VERY_HIGH 0 } - descText @MENUS1_SELECT_THE_RESOLUTION - cvar "ui_r_picmip" - - visible 0 - - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_quality - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_QUALITY - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_DEFAULT 0 @MENUS0_16_BIT 16 @MENUS0_32_BIT 32 } - descText @MENUS1_SELECT_THE_NUMBER_OF - cvar "ui_r_texturebits" - - visible 0 - - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name texture_filter - group video - type ITEM_TYPE_MULTI - text @MENUS0_TEXTURE_FILTER - rect 305 331 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarStrList { @MENUS1_BILINEAR , "GL_LINEAR_MIPMAP_NEAREST" , @MENUS1_TRILINEAR , "GL_LINEAR_MIPMAP_LINEAR" } - descText @MENUS1_ADJUST_HOW_WELL_THE_TEXTURES - cvar "ui_r_texturemode" - - visible 0 - - mouseenter - { - show highlight9 - } - mouseexit - { - hide highlight9 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name simple_shaders - group video - type ITEM_TYPE_MULTI - text @MENUS0_DETAILED_SHADERS - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_HIDE_OR_UNHIDE_TEXTURES - cvar "ui_r_detailtextures" - - visible 0 - - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - action - { - play "sound/interface/button1.wav" ; - uiScript glCustom ; - setcvar ui_r_modified 1 ; - show applyChanges - } - } - - itemDef - { - name compress_textures - group video_obsolete - type ITEM_TYPE_MULTI - text @MENUS0_COMPRESSED_TEXTURES - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - descText @MENUS1_TAKE_ADVANTAGE_OF_3D - cvar "ui_r_ext_compress_textures" - - visible 0 - - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - action - { - play "sound/interface/button1.wav" - uiScript glCustom - setcvar ui_r_modified 1 - show applyChanges - } - } - - // APPLY CHANGES BUTTON - itemDef - { - name applybutton_glow - group none - style WINDOW_STYLE_SHADER - rect 120 383 170 30 - background "gfx/menus/menu_blendbox2" // Frame around button - forecolor 1 0.5 0.5 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name applyChanges - group none - text @MENUS0_APPLY_CHANGES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 120 383 170 30 - font 3 - textscale 0.9 - textalignx 170 - textaligny 5 - textalign ITEM_ALIGN_RIGHT - textstyle 3 - forecolor 1 0 0 1 - backcolor 0 0 1 0 - visible 0 - - mouseEnter - { - show applybutton_glow - } - mouseExit - { - hide applybutton_glow - } - action - { - play "sound/interface/button1.wav" ; - show setup_background ; - show vidrestart ; - setfocus vidrestart_no ; - hide video ; - hide video2 ; - hide applybutton_glow ; - } - } - - itemDef - { - name gl_extensions - group video - type ITEM_TYPE_MULTI - text @MENUS1_GL_EXTENSIONS - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - cvar ui_r_allowExtensions - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - // appearance_slot 3 - descText @MENUS2_TOGGLE_GL_EXTENSIONS - - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - action - { - play "sound/interface/button1.wav" - setcvar ui_r_modified 1 - show applyChanges - } - } - - - //---------------------------------------------------------------------------------------------- - // - // VIDEO RESTART - // - //---------------------------------------------------------------------------------------------- - // Faint red box - itemDef - { - name vidrestart_background - group vidrestart - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_boxred" // Frame - forecolor 1 1 1 0.5 - visible 0 - decoration - } - - itemDef - { - name vidrestart_text1 - group vidrestart - text @MENUS0_THIS_WILL_APPLY_VIDEO - text2 @MENUS0_AND_RETURN_TO_THE_MAIN - rect 305 230 290 20 - textalign ITEM_ALIGN_CENTER - text2aligny 18 - textalignx 145 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name vidrestart_text2 - group vidrestart - text @MENUS0_VID_RESTART3 - rect 305 300 290 20 - textalign ITEM_ALIGN_CENTER - textalignx 145 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - } - - - - itemDef - { - name vidrestart_yes_button - group none - style WINDOW_STYLE_SHADER - rect 467 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 4 - } - - // YES button - itemDef - { - name vidrestart_yes - group vidrestart - text @MENUS0_YES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 467 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textalignx 60 - textaligny 0 - descText @MENUS0_APPLY_CHANGES_AND_THEN - forecolor 0.65 0.65 1 1 - visible -1 - // appearance_slot 5 - - action - { - play "sound/interface/button1.wav" ; - close all ; - uiScript updatevideosetup ; - } - mouseEnter - { - show vidrestart_yes_button - } - mouseExit - { - hide vidrestart_yes_button - } - - } - - itemDef - { - name vidrestart_no_button - group none - style WINDOW_STYLE_SHADER - rect 305 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 3 - } - - // CANCEL button - itemDef - { - name vidrestart_no - group vidrestart - text @MENUS0_NO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 305 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textalignx 60 - textaligny -1 - descText @MENUS0_DO_NOT_APPLY_CHANGES - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 6 - action - { - play "sound/interface/button1.wav" ; - setfocus video1menubutton ; - show setup_background ; - hide vidrestart ; - show video ; - hide video2 ; - show applyChanges ; - hide vidrestart_yes_button ; - hide vidrestart_no_button ; - } - mouseEnter - { - show vidrestart_no_button - } - mouseExit - { - hide vidrestart_no_button - } - - } - - //---------------------------------------------------------------------------------------------- - // - // VIDEO 2 - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name gamma_text - group video2 - style WINDOW_STYLE_SHADER - rect 310 171 280 36 - background "gfx/menus/greyscale" // greyscale - forecolor 1 1 1 1 - visible 0 - decoration - // appearance_slot 1 - } - - - - itemDef - { - name bright_text - group video2 - text @MENUS0_ADJUST_BRIGHTNESS_SLIDER - text2 @MENUS0_THE_NUMBER_6_CAN_BARELY - text2aligny 14 - textalignx 128 - font 2 - textscale 0.8 - rect 305 211 256 20 - textalign ITEM_ALIGN_CENTER - forecolor 0.7 0.7 0.7 1 - visible 0 - // appearance_slot 2 - decoration - } - - itemDef - { - name brightness - group video2 - type ITEM_TYPE_SLIDER - text @MENUS0_VIDEO_BRIGHTNESS - cvarfloat "r_gamma" 1 .5 3 - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 3 - descText @MENUS1_ADJUST_THE_BRIGHTNESS - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - } - - itemDef - { - name shadows - group video2 - type ITEM_TYPE_MULTI - text @MENUS3_SHADOWS - descText @MENUS3_SHADOWS_DESC - cvar "cg_shadows" - cvarFloatList - { - @MENUS3_NONE 0 - @MENUS3_SHADOWS_SIMPLE 1 - @MENUS3_SHADOWS_VOLUMETRIC 2 -// "Projected" 3 - } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - action - { - play "sound/interface/button1.wav" ; - } - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - - } - - - itemDef - { - name video_sync - group video2 - type ITEM_TYPE_MULTI - text @MENUS3_VIDEO_SYNC - cvar "r_swapInterval" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_VIDEO_SYNC_DESC - - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - action - { - play "sound/interface/button1.wav" ; - - } - } - - - itemDef - { - name dynamic_light - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_DYNAMIC_LIGHTS - cvar "r_dynamiclight" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_TURN_ON_MOVING - - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - action - { - play "sound/interface/button1.wav" ; - - } - } - - itemDef - { - name wall_marks - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_WALL_MARKS - cvar "cg_marks" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 331 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_DISPLAY_SCORCH - - mouseenter - { - show highlight9 - } - mouseexit - { - hide highlight9 - } - action - { - play "sound/interface/button1.wav" - } - } - - itemDef - { - name video_mode - group video2 - type ITEM_TYPE_MULTI - text @MENUS0_ANISOTROPIC_FILTERING - cvarTest r_ext_texture_filter_anisotropic_avail - hideCvar { 0 } - cvar r_ext_texture_filter_anisotropic - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 5 - - descText @MENUS1_TOGGLE_ADVANCED_TEXTURE - - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - action - { - play "sound/interface/button1.wav" - } - } - - itemDef - { - name light_flares - group video2-obsolete - type ITEM_TYPE_MULTI - text @MENUS0_LIGHT_FLARES - cvar "r_flares" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_TOGGLE_TO_SHOW_HALOS - - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - action - { - play "sound/interface/button1.wav" - } - } - - itemDef - { - name advancedvideobutton_glow - group none - style WINDOW_STYLE_SHADER - rect 355 391 200 20 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name advancedvideo - group video2 - type ITEM_TYPE_BUTTON - text @MENUS2_SHOW_DRIVER_INFO - rect 355 391 200 20 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 100 - font 2 - textscale 0.8 - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 5 - descText @MENUS2_SHOW_ADVANCED_INFORMATION - - mouseenter - { - show advancedvideobutton_glow - } - mouseexit - { - hide advancedvideobutton_glow - } - action - { - play "sound/interface/button1.wav" - setfocus video2menubutton - hide advancedvideobutton_glow - open videodriverMenu - } - } - - //---------------------------------------------------------------------------------------------- - // - // SOUND FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name effects_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS0_EFFECTS_VOLUME - cvarfloat "s_volume" 0 0 1 - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS1_ADJUST_VOLUME_FOR_SOUND - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - itemDef - { - name music_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS0_MUSIC_VOLUME - cvarfloat "s_musicvolume" 0 0 1 - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 2 - descText @MENUS1_ADJUST_VOLUME_FOR_MUSIC - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - itemDef - { - name voice_volume - group sound - type ITEM_TYPE_SLIDER - text @MENUS1_VOICE_VOLUME - cvarfloat "s_volumevoice" 0 0 1 - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 120 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 2 - descText @MENUS2_ADJUST_VOLUME_FOR_SPEECH - action - { - play "sound/interface/button1.wav" ; - } - - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - itemDef - { - name sound_quality - group sound - type ITEM_TYPE_MULTI - text @MENUS0_SOUND_QUALITY - cvar "s_khz" - cvarFloatList { @MENUS0_LOW 11 @MENUS0_HIGH 22 } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 3 - descText @MENUS2_TRADE_CLARITY_OF_SOUND - - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - action - { - play "sound/interface/button1.wav" - uiScript update s_khz - } - } - - //---------------------------------------------------------------------------------------------- - // - // OPTION FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name draw_crosshair - group options - type ITEM_TYPE_MULTI - text @MENUS2_DRAW_CROSSHAIR - cvar "cg_drawcrosshair" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 171 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText @MENUS2_TOGGLE_TO_SHOW_OR_HIDE - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight1 - } - mouseexit - { - hide highlight1 - } - } - - - itemDef - { - name identifytarget - group options - type ITEM_TYPE_MULTI - text @MENUS0_IDENTIFY_TARGET - cvar "cg_crosshairIdentifyTarget" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText @MENUS2_TOGGLE_TO_HAVE_THE_CROSSHAIR - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - - itemDef - { - name slowmo - group options - type ITEM_TYPE_MULTI - text @MENUS2_SLOW_MOTION_DEATH - cvar "d_slowmodeath" - cvarFloatList - { - @MENUS2_NEVER 0 - @MENUS2_ON_DEATH 1 - @MENUS2_RARELY 2 - @MENUS1_NORMAL 3 - @MENUS2_OFTEN 4 - @MENUS2_FREQUENTLY 5 - @MENUS2_EXCESSIVELY 6 - } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_THE_FREQUENCY - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - - itemDef - { - name force3rd - group options - type ITEM_TYPE_MULTI - text @MENUS2_3RD_PERSON_LIGHTSABER - cvar "cg_saberAutoThird" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_WHEN_READYING_LIGHTSABER - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - - itemDef - { - name force1st - group options - type ITEM_TYPE_MULTI - text @MENUS2_1ST_PERSON_GUNS - cvar "cg_gunAutoFirst" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 251 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_WHEN_PUTTING_AWAY_SABER - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight5 - } - mouseexit - { - hide highlight5 - } - } - - - itemDef - { - name dismemberment - group options - type ITEM_TYPE_MULTI - text @MENUS2_DISMEMBERMENT - cvar "g_dismemberment" - cvarFloatList - { - @MENUS0_OFF 0 - @MENUS0_ON 3 - } - cvarTest ui_iscensored - hideCvar { 1 } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_WHAT_LIGHTSABER - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - } - -// Weapon Sway. Yes, this is nutty. Two cvars here, one removes weapon sway, the other adds it. - itemDef - { - name weaponswayon - group options - type ITEM_TYPE_MULTI - text @MENUS3_VIEW_SWAYING - descText @MENUS3_VIEW_SWAYING_DESC - cvar "ui_disableWeaponSway" - cvarFloatList - { - @MENUS0_ON 0 - @MENUS0_OFF 1 - } - cvarTest "ui_disableWeaponSway" - showCvar - { - "0" - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - - action - { - play "sound/interface/button1.wav" - exec "exec noMotion.cfg" ; - show weaponswayoff ; - setfocus weaponswayoff - } - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } - - itemDef - { - name weaponswayoff - group options - type ITEM_TYPE_MULTI - text @MENUS3_VIEW_SWAYING - descText @MENUS3_VIEW_SWAYING_DESC - cvar "ui_disableWeaponSway" - cvarFloatList - { - @MENUS0_ON 0 - @MENUS0_OFF 1 - } - cvarTest "ui_disableWeaponSway" - hideCvar - { - "0" - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - - action - { - play "sound/interface/button1.wav" - exec "exec restoreMotion.cfg" ; - show weaponswayon ; - setfocus weaponswayon - } - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } - - - -/* - itemDef - { - name dismembermentprob - group options_obsolete - type ITEM_TYPE_MULTI - text @MENUS2_DISMEMBER_PROBABILITY - cvar "g_dismemberProbabilities" - cvarFloatList - { - @MENUS2_RARE 2 - @MENUS1_NORMAL 1 - @MENUS2_EXCESSIVE 0 - } - rect 305 311 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_SELECT_FREQUENCY_OF_DISMEMBERMENT - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight8 - } - mouseexit - { - hide highlight8 - } - } -*/ - - itemDef - { - name text - group options - type ITEM_TYPE_MULTI - text @MENUS0_TEXT - cvar "sp_language" - cvarFloatList - { - "English" 0 - "Francais" 1 - "Deutsch" 2 - } - rect 305 351 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS2_CHOOSE_THE_LANGUAGE_FOR - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight10 - } - mouseexit - { - hide highlight10 - } - } - - itemDef - { - name voice - group options - type ITEM_TYPE_MULTI - text @MENUS1_VOICE - cvar "s_language" - cvarStrList - { - "English", "english" - "Francais" "francais" - "Deutsch" "deutsch" - } - rect 305 371 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_CHOOSE_THE_LANGUAGE_TO - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight11 - } - mouseexit - { - hide highlight11 - } - } - - itemDef - { - name voice - group options - type ITEM_TYPE_MULTI - text @MENUS1_SUBTITLES - cvar "g_subtitles" - cvarFloatList - { - @MENUS3_NONE 0 - @MENUS3_IN_CINEMATICS 2 -// @MENUS3_ALL_VOICEOVERS 1 - } - rect 305 391 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_TOGGLE_WHETHER_SUBTITLES - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight12 - } - mouseexit - { - hide highlight12 - } - } - - - -// This menu option is no longer used. - itemDef - { - name sync_frame - group options_obsolete - type ITEM_TYPE_MULTI - text @MENUS1_SYNC_EVERY_FRAME - cvar "r_finish" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText @MENUS3_TOGGLE_TO_PREVENT_VIDEO - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - //---------------------------------------------------------------------------------------------- - // - // MOD GAME MENU specific stuff - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name serverinfo - group mods - rect 302 184 300 200 - type ITEM_TYPE_LISTBOX - style WINDOW_STYLE_FILLED - elementwidth 120 - elementheight 16 - font 2 - textscale 1 - border 1 - bordersize 1 - bordercolor .5 .5 .5 .5 - forecolor 0.65 0.65 1 1 - backcolor 0 0 .5 .25 - outlinecolor .5 .5 .5 .5 - elementtype LISTBOX_TEXT - feeder 9 - notselectable - visible 0 - columns 2 2 40 20 200 80 30 - } - - itemDef - { - name loadmod_button - group none - style WINDOW_STYLE_SHADER - rect 305 391 300 20 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - decoration - } - - itemDef - { - name loadmod - group mods - text @MENUS1_LOAD_MOD - descText @MENUS1_LOAD_CHOSEN_MOD - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 305 391 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - font 2 - textscale 0.8 - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 2 - action - { - play "sound/interface/button1.wav" -// uiScript loadgame - } - - mouseEnter - { - show loadmod_button - } - mouseExit - { - hide loadmod_button - } - } - - //---------------------------------------------------------------------------------------------- - // - // RESET DEFAULTS - // - //---------------------------------------------------------------------------------------------- - // Faint red box - itemDef - { - name vidrestart_background - group defaults - style WINDOW_STYLE_SHADER - rect 300 171 300 250 - background "gfx/menus/menu_boxred" // Frame - forecolor 1 1 1 0.5 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS0_WARNING - rect 305 191 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS2_THIS_WILL_SET_ALL_GAME - text2 @MENUS2_TO_THEIR_FACTORY_SETTINGS - rect 305 231 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - text2aligny 20 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - itemDef - { - name options - group defaults - text @MENUS0_VID_RESTART3 - rect 305 291 300 20 - textalign ITEM_ALIGN_CENTER - textalignx 150 - font 2 - textscale 1 - forecolor 1 1 0 1 - visible 0 - decoration - } - - - itemDef - { - name default_yes_button - group highlights - style WINDOW_STYLE_SHADER - rect 467 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 4 - } - - // YES button - lose reset defaults - itemDef - { - name default_yes - group defaults - text @MENUS0_YES - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 467 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 60 - textaligny 0 - descText @MENUS0_USE_DEFAULT_SETTINGS - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 5 - - action - { - play "sound/interface/button1.wav" ; - hide highlights ; - close all ; - uiscript resetdefaults - } - mouseEnter - { - show default_yes_button - } - mouseExit - { - hide default_yes_button - } - - } - - itemDef - { - name default_no_button - group highlights - style WINDOW_STYLE_SHADER - rect 305 386 120 32 - background "gfx/menus/menu_buttonback" // Frame around button - forecolor 1 1 1 1 - decoration - visible 0 - // appearance_slot 3 - } - - // NO button - return to Main Menu - itemDef - { - name default_no - group defaults - text @MENUS0_NO - type ITEM_TYPE_BUTTON - style WINDOW_STYLE_EMPTY - rect 305 386 120 32 - font 2 - textscale 1 - textalign ITEM_ALIGN_CENTER - textstyle 3 - textalignx 60 - textaligny 0 - descText @MENUS0_DO_NOT_RESET_DEFAULT - forecolor 0.65 0.65 1 1 - visible 0 - // appearance_slot 6 - action - { - play "sound/interface/button1.wav" - hide highlights ; - hide default_no_button - close all ; - open mainMenu ; - } - mouseEnter - { - show default_no_button - } - mouseExit - { - hide default_no_button - } - } - - //---------------------------------------------------------------------------------------------- - // - // SPEEDRUN FIELDS - // - //---------------------------------------------------------------------------------------------- - itemDef - { - name draw_secrets - group speedrun - type ITEM_TYPE_MULTI - text "Show Secret Count:" - cvar "cg_drawSecrets" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 191 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText "Toggle to show number of found and total secrets." - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight2 - } - mouseexit - { - hide highlight2 - } - } - - - itemDef - { - name draw_overbounceinfo - group speedrun - type ITEM_TYPE_MULTI - text "Show Overbounce Info:" - cvar "cg_drawOverbounceInfo" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 211 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - descText "Toggle to show or hide overbounce information." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight3 - } - mouseexit - { - hide highlight3 - } - } - - - itemDef - { - name draw_speed - group speedrun - type ITEM_TYPE_MULTI - text "Show Speed:" - cvar "cg_drawSpeed" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 231 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide speed display." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight4 - } - mouseexit - { - hide highlight4 - } - } - - - itemDef - { - name draw_strafehelper - group speedrun - type ITEM_TYPE_MULTI - text "Strafe Helper:" - cvar "cg_drawStrafeHelper" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 271 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide the strafe helper." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight6 - } - mouseexit - { - hide highlight6 - } - } - - - itemDef - { - name draw_jumphelper - group speedrun - type ITEM_TYPE_MULTI - text "Jump Height Helper:" - cvar "cg_drawJumpHelper" - cvarFloatList { @MENUS0_OFF 0 @MENUS0_ON 1 } - rect 305 291 300 20 - textalign ITEM_ALIGN_RIGHT - textalignx 165 - textaligny -2 - font 2 - textscale 0.8 - forecolor 1 1 1 1 - visible 0 - // appearance_slot 1 - descText "Toggle to show or hide the jump height helper." - - action - { - play "sound/interface/button1.wav" - } - mouseenter - { - show highlight7 - } - mouseexit - { - hide highlight7 - } - } - } -} diff --git a/code/base/assets_randomizer.pk3 b/code/base/assets_randomizer.pk3 deleted file mode 100644 index abcd498a4f4c25c72ceba63a0f0899ba822c2094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15222 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 ZzZ?Fa<-sBT^FpBi2KGPmV$T0m{{sO@uqOZj diff --git a/code/base/ext_data/NPCs.cfg b/code/base/ext_data/NPCs.cfg deleted file mode 100644 index 68a07192..00000000 --- a/code/base/ext_data/NPCs.cfg +++ /dev/null @@ -1,2315 +0,0 @@ -//Star Wars -/* -defaults and explanations of fields: - aggression 3 How likely they are to attack (from 1 (least) to 5 (most)) - aim 3 How good their aim is (from 1 (worst) to 5 (best)) - earshot 1024 How far in map units they can hear, in map units - evasion 3 How likely they are to take cover or defensive maneuvers (from 1 (least) to 5 (most)) - hfov 45 Horizontal field of view, in angles - intelligence 3 How smart they are, in general (from 1 (least) to 5 (most)) - move 3 How complex their moves are when evading or in combat (from 1 (least) to 5 (most)) - reactions 3 How quickly they react (from 1 (worst) to 5 (best)) - shootDistance 0 Overrides current weapon's max range - vfov 34 Vertical field of view, in angles - vigilance 0.1 How likely they are to notice something (from 0 (never) to 1 (always)) - visrange 2048 How far away they can see something, in map units - race none human, borg, parasite, klingon, malon, hirogen, stasis, species8472, dreadnought, harvester, reaver, avatar, vulcan - playerTeam none player, enemy, neutral - enemyTeam none player, enemy, neutral - - health 100 Health of entity (if not supplied by designer) - - moveType "runjump" Which movetype they can be (other choices are "static", "walk" and "flyswim" - yawSpeed 50 How quickly they can turn - walkSpeed 150 How fast they walk - runSpeed 300 How fast they run - acceleration 15 Acceleration (accel x 20fps = speed up per second, so accel of 15 means they can go from 0 to 300 in one second) - Accel of 0 means don't accel/decel - just start/stop (good if you're a slow mover anyway and/or robotic - like a Borg) - - scaleX 100 X (horiz) scale, 100 is normal 100% scale - scaleY 100 Y (horiz) scale, 100 is normal 100% scale - scaleZ 100 Z (vert) scale, 100 is normal 100% scale - scale 100 Sets all above 3 to what you specify - headModel "hazard" model directory/skin name - torsoModel "hazard" model directory/skin name - legsModel "hazard" model directory/skin name - headYawRangeLeft 70 How far left you can turn your head (angles) - headYawRangeRight 70 How far right you can turn your head (angles) - headPitchRangeUp 60 How far up you can tilt your head (angles) - headPitchRangeDown 60 How far down you can tilt your head (angles) - torsoYawRangeLeft 60 How far left you can turn your torso (angles) - torsoYawRangeRight 60 How far right you can turn your torso (angles) - torsoPitchRangeUp 30 How far up you can tilt your torso (angles) - torsoPitchRangeDown 70 How far down you can tilt your torso (angles) - - snd "munro" subdirectory of sound/player from which to get custom sounds (pain, death, jump, etc.) - dismemberProbHead 0 probability of head being dismembered ( from 0 (never) to 100 (always) ) - dismemberProbArms 0 probability of arms being dismembered ( from 0 (never) to 100 (always) ) - dismemberProbHands 0 probability of hands being dismembered ( from 0 (never) to 100 (always) ) - dismemberProbLegs 0 probability of legs being dismembered ( from 0 (never) to 100 (always) ) - dismemberProbWaist 0 probability of waist being dismembered ( from 0 (never) to 100 (always) ) -*/ - -//Characters -munro -{ - fullName "Katarn, Kyle" - playerModel kyle - saberColor blue - reactions 4 - aim 5 - move 3 - aggression 5 - evasion 5 - intelligence 5 - playerTeam player -// race human - class kyle - snd munro -} - -Kyle -{ - fullName "Katarn, Kyle" - playerModel kyle - saberColor blue - reactions 4 - aim 5 - move 3 - aggression 5 - evasion 5 - intelligence 5 - playerTeam player -// race human - class kyle - snd kyle - sndcombat kyle - sndjedi kyle - dismemberProbHead 1 - dismemberProbArms 1 - dismemberProbHands 20 - dismemberProbLegs 1 - dismemberProbWaist 1 -} - -Tavion -{ - playerModel tavion - rank commander - saberColor red - reactions 3 - aim 3 - move 5 - aggression 3 - evasion 4 - intelligence 5 - hfov 160 - vfov 160 - playerTeam enemy - enemyTeam player -// race human - class tavion - snd tavion - sndcombat tavion - sndjedi tavion - yawSpeed 120 - walkSpeed 55 - runSpeed 200 - health 300 - dismemberProbHead 10 - dismemberProbArms 35 - dismemberProbLegs 10 - dismemberProbHands 50 - dismemberProbWaist 10 -} - -Lando -{ - fullName "Calrissian, Lando" - playerModel lando - snd lando - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy -// race human - class lando - snd lando - sndcombat lando - sndextra lando - sndjedi lando - walkSpeed 55 - runSpeed 200 - yawspeed 120 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbHands 0 - dismemberProbLegs 0 - dismemberProbWaist 0 -} - -Reelo -{ - fullName "Baruk, Reelo" - playerModel reelo - snd reelo - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class reelo - snd reelo - sndcombat reelo - sndextra reelo - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 5 - dismemberProbArms 1 - dismemberProbHands 20 - dismemberProbLegs 1 - dismemberProbWaist 0 -} - -Jan -{ - fullName "Ors, Jan" - playerModel jan - rank lt - reactions 3 - aim 5 - move 3 - aggression 3 - evasion 3 - intelligence 3 - playerTeam player - enemyTeam enemy - class jan - snd jan - sndcombat jan - sndextra jan - yawSpeed 140 - walkSpeed 55 - runSpeed 200 -// race human - snd jan - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbHands 1 - dismemberProbLegs 0 - dismemberProbWaist 0 -} - -Galak -{ - fullName "Fyyar, Galak" - playerModel galak - snd galak - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank captain - playerTeam enemy - enemyTeam player -// race klingon - class imperial - yawspeed 90 - walkSpeed 55 - runSpeed 200 -} - -Galak_Mech -{ - fullName "Fyyar, Galak" - playerModel galak_mech - health 1000 - width 20 - height 88 - crouchheight 88 - snd galak_mech - reactions 3 - aim 5 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class galak_mech - snd galak - sndcombat galak - sndextra galak - yawSpeed 50 - walkSpeed 45 - runSpeed 150 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbHands 0 - dismemberProbLegs 0 - dismemberProbWaist 0 - headPitchRangeUp 60 - headPitchRangeDown 60 - torsoPitchRangeUp 60 - torsoPitchRangeDown 60 -} - - -Desann -{ - fullName "Desann" - playerModel desann - saberColor red - rank captain - reactions 3 - aim 3 - move 5 - aggression 3 - evasion 5 - intelligence 5 - hfov 160 - vfov 160 - scale 135 - height 78 - crouchheight 42 - width 18 - playerTeam enemy - enemyTeam player -// race human - class desann - yawSpeed 120 - walkSpeed 55 - runSpeed 200 - snd desann - sndcombat desann - sndjedi desann - health 500 - dismemberProbHead 10 - dismemberProbArms 35 - dismemberProbLegs 10 - dismemberProbHands 50 - dismemberProbWaist 10 -} - -Luke -{ - fullName "Skywalker, Luke" - playerModel luke - saberColor green - rank captain - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 5 - intelligence 3 - playerTeam player - enemyTeam enemy - class luke - yawSpeed 140 - walkSpeed 55 - runSpeed 200 -// race human - snd luke - sndcombat luke - sndjedi luke - health 200 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbLegs 0 - dismemberProbHands 0 - dismemberProbWaist 0 -} - -MonMothma -{ - fullName "Mon Mothma" - playerModel monmothma - snd monmothma - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy -// race human - class monmotha - walkSpeed 55 - runSpeed 200 - yawspeed 90 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbLegs 0 - dismemberProbHands 0 - dismemberProbWaist 0 -} - -Bartender -{ - fullName "Bartender" - playerModel chiss - snd bartender - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam neutral - enemyTeam neutral -// race human - class bartender - walkSpeed 55 - runSpeed 200 - yawspeed 90 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbLegs 0 - dismemberProbHands 0 - dismemberProbWaist 0 -} - -MorganKatarn -{ - fullName "MorganKatarn" - playerModel morgan - snd morgan - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam neutral - enemyTeam neutral -// race human - class morgan - walkSpeed 55 - runSpeed 200 - yawspeed 90 - dismemberProbHead 0 - dismemberProbArms 0 - dismemberProbLegs 0 - dismemberProbHands 0 - dismemberProbWaist 0 -} - -Prisoner -{ - playerModel prisoner - snd prisoner - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy - class prisoner - snd prisoner1 - sndcombat prisoner1 - sndextra prisoner1 - walkSpeed 55 - runSpeed 200 - yawspeed 110 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -Prisoner2 -{ - playerModel prisoner - snd prisoner - surfOff "head head_face" - surfOn "head_off head_face_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy - class prisoner - snd prisoner2 - sndcombat prisoner2 - sndextra prisoner2 - walkSpeed 55 - runSpeed 200 - yawspeed 110 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -//NPC Humanoids -Jedi -{ - playerModel jedi - saberColor yellow - rank lt - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 2 - intelligence 3 - playerTeam player - enemyTeam enemy - class jedi - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - snd jedi1 - sndcombat jedi1 - sndjedi jedi1 - health 200 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -Jedi2 -{ - playerModel jedi - saberColor orange - rank lt - customSkin j2 - surfOff "head head_face" - surfOn "head_off head_face_off" - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 2 - intelligence 3 - playerTeam player - enemyTeam enemy - class jedi - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - snd jedi2 - sndcombat jedi2 - sndjedi jedi2 - health 200 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -JediF -{ - playerModel jan - surfOff "torso_vest hips_chaps torso_computer head_goggles torso_comp hips_belt" - surfOn "torso_augment_off hips_augment_off hips_torso_off" - saberColor random - rank lt - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 2 - intelligence 3 - playerTeam player - enemyTeam enemy - class jedi - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - snd jan - sndcombat jan - sndjedi jan - health 200 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -JediTrainer -{ - playerModel jeditrainer - saberColor purple - rank commander - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 5 - intelligence 5 - playerTeam player - enemyTeam enemy - class jedi - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - snd jedi1 - sndcombat jedi1 - sndjedi jedi1 - health 400 - dismemberProbHead 0 - dismemberProbArms 5 - dismemberProbLegs 0 - dismemberProbHands 10 - dismemberProbWaist 0 -} - -Rebel -{ - playerModel rebel - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy -// race human - class rebel - snd rebel1 - sndcombat rebel1 - sndextra rebel1 - yawspeed 120 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Rebel2 -{ - playerModel rebel - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy -// race human - class rebel - snd rebel2 - sndcombat rebel2 - sndextra rebel2 - yawspeed 120 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -BespinCop -{ - playerModel bespin_cop - health 40 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy - walkSpeed 55 - runSpeed 200 - yawspeed 120 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -// race bespincop - class bespin_cop - snd bespincop1 - sndcombat bespincop1 - sndextra bespincop1 -} - -BespinCop2 -{ - playerModel bespin_cop - health 40 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam player - enemyTeam enemy - walkSpeed 55 - runSpeed 200 - yawspeed 120 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -// race bespincop - class bespin_cop - snd bespincop2 - sndcombat bespincop2 - sndextra bespincop2 -} - -Ugnaught -{ - playerModel ugnaught - scale 75 - health 10 - snd ugnaught - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam neutral - enemyTeam player -// race klingon - class ugnaught - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Ugnaught2 -{ - playerModel ugnaught - surfOff "l_hand_purse" - surfOn "r_hand_tool_off" - scale 75 - health 10 - snd ugnaught - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam neutral - enemyTeam player -// race klingon - class ugnaught - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Gran -{ - playerModel gran - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - health 30 - playerTeam enemy - enemyTeam player -// race klingon - class gran - snd gran1 - sndcombat gran1 - sndextra gran1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Gran2 -{ - playerModel gran - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - health 30 - playerTeam enemy - enemyTeam player -// race klingon - class gran - snd gran2 - sndcombat gran2 - sndextra gran2 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -GranShooter -{ - playerModel gran - surfOff "l_leg_kneeguard" - reactions 3 - aim 5 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 40 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class gran - snd gran1 - sndcombat gran1 - sndextra gran1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -GranBoxer -{ - playerModel gran - surfOff "l_leg_kneeguard r_leg_kneeguard" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 50 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class gran - snd gran2 - sndcombat gran2 - sndextra gran2 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Rodian -{ - playerModel rodian - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 25 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class rodian - snd rodian1 - sndcombat rodian1 - sndextra rodian1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - visrange 8192 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Rodian2 -{ - playerModel rodian - surfOff "hips_belt torso_vest" - surfOn "torso_augment_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 20 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class rodian - snd rodian2 - sndcombat rodian2 - sndextra rodian2 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Weequay -{ - playerModel weequay -//FIXME: randomize these somehow, also belt... - surfOff "hips_lowerarmor" - surfOn "hips_torso_augment_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 30 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class weequay - snd weequay - sndcombat weequay - sndextra weequay - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Weequay2 -{ - playerModel weequay - surfOff "head_l_hairback hips_r_strap hips_r_packsmall" - surfOn "head_r_hairshoulder_off hips_l_packsmall_off hips_l_strap_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 30 - rank crewman - playerTeam enemy - enemyTeam player - class weequay - snd weequay - sndcombat weequay - sndextra weequay - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Weequay3 -{ - playerModel weequay - surfOff "head_l_hairback hips_l_packlarge hips_l_packwide hips_r_strap hips_r_packsmall" - surfOn "head_r_hairback_off hips_l_packsmall_off hips_l_strap_off hips_r_packlarge_off hips_r_packwide_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 30 - rank crewman - playerTeam enemy - enemyTeam player - class weequay - snd weequay - sndcombat weequay - sndextra weequay - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Weequay4 -{ - playerModel weequay - surfOff "head_l_hairback hips_l_packlarge hips_l_packwide" - surfOn "head_l_hairshoulder_off hips_r_packlarge_off hips_r_packwide_off" - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 30 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class weequay - snd weequay - sndcombat weequay - sndextra weequay - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Trandoshan -{ - playerModel trandoshan - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - health 40 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class trandoshan - snd trandoshan1 - sndcombat trandoshan1 - sndextra trandoshan1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 1 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -StormTrooper -{ - playerModel stormtrooper - surfOff torso_pauldron_off - surfOn "torso_armor_neck_augment torso_body_neck_augment" - health 30 - headPitchRangeDown 30 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd st1 - sndcombat st1 - sndextra st1 - yawspeed 70 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -StormTrooper2 -{ - playerModel stormtrooper - surfOff torso_pauldron_off - surfOn "torso_armor_neck_augment torso_body_neck_augment" - health 30 - headPitchRangeDown 30 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd st2 - sndcombat st2 - sndextra st2 - yawspeed 70 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -STOfficer -{ - playerModel stormtrooper - surfOn torso_pauldron_off - surfOff "torso_armor_neck_augment torso_body_neck_augment" - health 60 - headPitchRangeDown 30 - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 5 - intelligence 5 - rank ensign - scale 105 - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 68 - crouchheight 52 - walkSpeed 51 - runSpeed 200 - snd stofficer1 - sndcombat stofficer1 - sndextra stofficer1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -StormPilot -{ - playerModel stormpilot - health 30 - headPitchRangeDown 30 - reactions 3 - aim 5 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player - class stormtrooper - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd st3 - sndcombat st3 - sndextra st3 - yawspeed 80 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -STOfficerAlt -{ - playerModel stormtrooper - surfOn torso_pauldron_off - surfOff "torso_armor_neck_augment torso_body_neck_augment" - health 60 - headPitchRangeDown 30 - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 5 - intelligence 5 - rank ensign - scale 105 - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 68 - crouchheight 52 - walkSpeed 51 - runSpeed 200 - snd stofficer2 - sndcombat stofficer2 - sndextra stofficer2 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -STCommander -{ - playerModel stormtrooper - surfOn torso_pauldron_off - surfOff "torso_armor_neck_augment torso_body_neck_augment" - health 60 - headPitchRangeDown 30 - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 5 - intelligence 5 - rank ensign - scale 105 - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 68 - crouchheight 52 - walkSpeed 51 - runSpeed 200 - snd stofficer2 - sndcombat stofficer2 - sndextra stofficer2 - yawspeed 110 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -SwampTrooper -{ - playerModel swamptrooper - headPitchRangeDown 30 - health 70 - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 3 - intelligence 3 - scale 110 - playerTeam enemy - enemyTeam player -// race klingon - class swamptrooper - height 68 - crouchheight 52 - snd swamp1 - sndcombat swamp1 - sndextra swamp1 - yawspeed 100 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -SwampTrooper2 -{ - playerModel swamptrooper - headPitchRangeDown 30 - health 70 - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 3 - intelligence 3 - scale 110 - playerTeam enemy - enemyTeam player -// race klingon - class swamptrooper - height 68 - crouchheight 52 - snd swamp2 - sndcombat swamp2 - sndextra swamp2 - yawspeed 100 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -RocketTrooper -{ - playerModel stormtrooper - surfOn torso_pauldron_off - surfOff "torso_armor_neck_augment torso_body_neck_augment" - health 60 - headPitchRangeDown 30 - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 5 - intelligence 5 - rank ensign - scale 110 - playerTeam enemy - enemyTeam player -// race klingon - class stormtrooper - height 68 - crouchheight 52 - walkSpeed 51 - runSpeed 200 - snd st3 - sndcombat st3 - sndextra st3 - yawspeed 100 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -Imperial -{ - playerModel imperial - surfOff l_arm_key - health 20 - reactions 2 - aim 2 - move 2 - aggression 2 - evasion 2 - intelligence 2 - rank lt - playerTeam enemy - enemyTeam player -// race klingon - class imperial - snd io2 - sndcombat io2 - sndextra io2 - yawspeed 110 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -ImpOfficer -{ - playerModel imperial - surfOff l_arm_key - customSkin officer - health 40 - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 3 - intelligence 3 - rank ltcomm - playerTeam enemy - enemyTeam player -// race klingon - class imperial - snd io1 - sndcombat io1 - sndextra io1 - yawspeed 110 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -ImpCommander -{ - playerModel imperial - surfOff l_arm_key - customSkin commander - health 80 - reactions 4 - aim 4 - move 4 - aggression 4 - evasion 4 - intelligence 4 - rank commander - playerTeam enemy - enemyTeam player -// race klingon - class imperial -// snd io3 -// sndcombat io3 -// sndextra io3 - snd io1 - sndcombat io1 - sndextra io1 - yawspeed 110 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -ImpWorker -{ - playerModel imperial_worker - headPitchRangeDown 30 - health 30 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race imperial - class impworker - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd worker1 - sndcombat worker1 - sndextra worker1 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -ImpWorker2 -{ - playerModel imperial_worker - headPitchRangeDown 30 - health 30 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race imperial - class impworker - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd worker2 - sndcombat worker2 - sndextra worker2 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -ImpWorker3 -{ - playerModel imperial_worker - headPitchRangeDown 30 - health 30 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - rank crewman - playerTeam enemy - enemyTeam player -// race imperial - class impworker - height 64 - crouchheight 48 - walkSpeed 51 - runSpeed 200 - snd worker3 - sndcombat worker3 - sndextra worker3 - yawspeed 90 - walkSpeed 55 - runSpeed 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 0 -} - -RebornAcrobat -{ - playerModel reborn - customSkin acrobat - saberColor red - rank crewman - reactions 3 - aim 3 - move 5 - aggression 3 - evasion 3 - intelligence 5 - hfov 160 - vfov 160 - scale 96 - playerTeam enemy - enemyTeam player -// race human - class reborn - snd reborn1 - sndcombat reborn1 - sndjedi reborn1 - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - health 100 - dismemberProbHead 0 - dismemberProbArms 20 - dismemberProbLegs 0 - dismemberProbHands 30 - dismemberProbWaist 0 -} - -Reborn -{ - playerModel reborn - saberColor red - reactions 1 - aim 1 - move 1 - aggression 1 - evasion 1 - intelligence 1 - hfov 120 - vfov 120 - scale 94 - playerTeam enemy - enemyTeam player -// race human - class reborn - snd reborn1 - sndcombat reborn1 - sndjedi reborn1 - yawSpeed 60 - walkSpeed 45 - runSpeed 180 - health 40 - dismemberProbHead 0 - dismemberProbArms 20 - dismemberProbLegs 0 - dismemberProbHands 30 - dismemberProbWaist 0 -} - -RebornForceUser -{ - playerModel reborn - customSkin forceuser - saberColor red - rank ensign - reactions 3 - aim 3 - move 5 - aggression 2 - evasion 2 - intelligence 5 - hfov 160 - vfov 160 - scale 96 - playerTeam enemy - enemyTeam player -// race human - class reborn - snd reborn2 - sndcombat reborn2 - sndjedi reborn2 - yawSpeed 80 - walkSpeed 55 - runSpeed 200 - health 100 - dismemberProbHead 0 - dismemberProbArms 20 - dismemberProbLegs 0 - dismemberProbHands 30 - dismemberProbWaist 0 -} - -RebornFencer -{ - playerModel reborn - customSkin fencer - saberColor red - rank ltjg - reactions 3 - aim 3 - move 5 - aggression 4 - evasion 2 - intelligence 5 - hfov 160 - vfov 160 - scale 96 - playerTeam enemy - enemyTeam player -// race human - class reborn - snd reborn2 - sndcombat reborn2 - sndjedi reborn2 - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - health 100 - dismemberProbHead 0 - dismemberProbArms 20 - dismemberProbLegs 0 - dismemberProbHands 30 - dismemberProbWaist 0 -} - -RebornBoss -{ - playerModel reborn - customSkin boss - saberColor red - rank lt - reactions 3 - aim 3 - move 5 - aggression 4 - evasion 3 - intelligence 5 - hfov 160 - vfov 160 - playerTeam enemy - enemyTeam player -// race human - class reborn - snd reborn3 - sndcombat reborn3 - sndjedi reborn3 - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - health 150 - dismemberProbHead 0 - dismemberProbArms 20 - dismemberProbLegs 0 - dismemberProbHands 30 - dismemberProbWaist 0 -} - -ShadowTrooper -{ - playerModel shadowtrooper - saberColor red - rank ltcomm - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 4 - intelligence 5 - hfov 160 - vfov 160 - playerTeam enemy - enemyTeam player -// race human - class shadowtrooper - snd shadow1 - sndcombat shadow1 - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - health 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 1 -} - -ShadowTrooper2 -{ - playerModel shadowtrooper - saberColor red - rank lt - reactions 5 - aim 5 - move 5 - aggression 5 - evasion 4 - intelligence 5 - hfov 160 - vfov 160 - playerTeam enemy - enemyTeam player -// race human - class shadowtrooper - snd shadow2 - sndcombat shadow2 - yawSpeed 140 - walkSpeed 55 - runSpeed 200 - health 200 - dismemberProbHead 0 - dismemberProbArms 10 - dismemberProbLegs 0 - dismemberProbHands 20 - dismemberProbWaist 1 -} -//NPC Monsters -Howler -{ - playerModel howler - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player - class howler - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - hFOV 120 - vfov 45 - snd howler - health 60 -} - -Minemonster -{ - playerModel minemonster - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player - class minemonster - snd mine - yawSpeed 160 - runSpeed 210 - walkSpeed 50 - hFOV 120 - vfov 45 - height 30 - width 9 - snd mine - health 40 -} - - -Glider -{ - playerModel glider - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race harvester - class glider - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - hFOV 120 - vfov 45 - snd glider -} - - -//NPC Droids -protocol -{ - playerModel protocol - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class protocol - snd protocol - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - height 48 - width 12 - hFOV 120 - vfov 45 - snd protocol -} - -protocol_imp -{ - playerModel protocol - surfOn head_off - surfOff head - customSkin imp - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class protocol - snd protocol - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - height 48 - width 12 - hFOV 120 - vfov 45 - snd protocol -} - -r2d2 -{ - playermodel r2d2 - headYawRangeLeft 180 - headYawRangeRight 180 - headPitchRangeUp 0 - headPitchRangeDown 0 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 10 - torsoPitchRangeDown 10 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class r2d2 - yawSpeed 120 - runSpeed 150 - walkSpeed 50 - height 40 - width 12 - hFOV 120 - vfov 45 - snd r2d2 -} - -r2d2_imp -{ - playermodel r2d2 - customSkin imp - headYawRangeLeft 180 - headYawRangeRight 180 - headPitchRangeUp 0 - headPitchRangeDown 0 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 10 - torsoPitchRangeDown 10 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class r2d2 - yawSpeed 120 - runSpeed 150 - walkSpeed 50 - height 40 - width 12 - hFOV 120 - vfov 45 - snd r2d2 -} - -r5d2 -{ - playerModel r5d2 - headYawRangeLeft 180 - headYawRangeRight 180 - headPitchRangeUp 0 - headPitchRangeDown 0 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 10 - torsoPitchRangeDown 10 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class r5d2 - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - height 40 - width 12 - hFOV 120 - vfov 45 - snd r5d2 -} - -r5d2_imp -{ - playerModel r5d2 - customSkin imp - headYawRangeLeft 180 - headYawRangeRight 180 - headPitchRangeUp 0 - headPitchRangeDown 0 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 10 - torsoPitchRangeDown 10 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class r5d2 - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - height 40 - width 12 - hFOV 120 - vfov 45 - snd r5d2 -} - -gonk -{ - playerModel gonk - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class gonk - yawSpeed 60 - runSpeed 40 - walkSpeed 30 - height 32 - width 12 - hFOV 120 - vfov 45 - snd gonk -} - - -mouse -{ - headmodel none - torsomodel none - legsmodel mouse - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam neutral - enemyTeam neutral -// race bot - class mouse - yawSpeed 120 - runSpeed 500 - walkSpeed 150 - height 16 - width 8 - hFOV 120 - vfov 45 - snd mouse -} - - -seeker -{ - headmodel none - torsomodel none - legsmodel remote - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 3 - intelligence 5 - playerTeam player - enemyTeam enemy -// race bot - class seeker - yawSpeed 120 - runSpeed 500 - walkSpeed 150 - height 32 - width 8 - hFOV 160 - vfov 45 - snd remote - moveType "flyswim" -} - -remote -{ - headmodel none - torsomodel none - legsmodel remote - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 3 - intelligence 5 - playerTeam enemy - enemyTeam player -// race bot - class remote - yawSpeed 120 - runSpeed 500 - walkSpeed 150 - height 32 - width 8 - hFOV 160 - vfov 45 - snd remote - moveType "flyswim" -} - -sentry -{ - playermodel sentry - health 100 - reactions 3 - aim 3 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player -// race bot - class sentry - health 150 - yawSpeed 120 - runSpeed 400 - walkSpeed 250 - height 48 - width 24 - hFOV 120 - vfov 160 - snd sentry -} - -interrogator -{ - playermodel interrogator - health 100 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player -// race bot - class interrogator - yawSpeed 120 - runSpeed 150 - walkSpeed 50 - height 24 - width 12 - hFOV 120 - vfov 45 - snd interrogator -} - - -probe -{ - playerModel probe - health 200 - headYawRangeLeft 180 - headYawRangeRight 180 - headPitchRangeUp 0 - headPitchRangeDown 0 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 10 - torsoPitchRangeDown 10 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player -// race bot - class probe - yawSpeed 60 - runSpeed 150 - walkSpeed 50 - height 110 - width 24 - hFOV 120 - vfov 45 - snd probe - moveType "flyswim" -} - -mark1 -{ - playerModel mark1 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - height 120 - width 36 - playerTeam enemy - enemyTeam player - health 300 -// race bot - class mark1 - yawSpeed 60 - runSpeed 150 - walkSpeed 70 - hFOV 120 - vfov 45 - snd mark1 -} - -mark2 -{ - playerModel mark2 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player -// race bot - class mark2 - yawSpeed 60 - runSpeed 150 - walkSpeed 75 - hFOV 120 - vfov 45 - snd mark2 -} - -atst -{ - playerModel atst -// headModel atst - //torsoModel atst - //legsModel atst - headYawRangeLeft 80 - headYawRangeRight 80 - headPitchRangeUp 30 - headPitchRangeDown 30 - torsoYawRangeLeft 0 - torsoYawRangeRight 0 - torsoPitchRangeUp 0 - torsoPitchRangeDown 0 - health 200 - reactions 3 - aim 1 - move 3 - aggression 3 - evasion 1 - intelligence 5 - playerTeam enemy - enemyTeam player - height 272 - width 80 -// race bot - class atst - yawSpeed 60 - runSpeed 150 - walkSpeed 150 - hFOV 120 - vfov 45 - snd atst -} - -test -{ - playerModel test - playerTeam player - enemyTeam neutral - class kyle -} diff --git a/code/base/ext_data/dms.dat b/code/base/ext_data/dms.dat deleted file mode 100644 index 2aeb1797..00000000 --- a/code/base/ext_data/dms.dat +++ /dev/null @@ -1,1238 +0,0 @@ -musicfiles -{ - kejimbase_explore - { - entry - { - marker0 0.000 - marker1 22.070 - marker2 53.723 - marker3 90.926 - } - exit - { - nextfile kejimbase_etr00 - time00 3.337 - time01 5.668 - time02 22.040 - time03 29.889 - time04 50.124 - time05 37.168 - time06 53.473 - time07 65.923 - time08 90.478 - time09 143.233 - time10 156.166 - time11 176.608 - time12 193.505 - } - exit - { - nextfile kejimbase_etr01 - time00 45.555 - time01 81.525 - time02 106.406 - time03 128.648 - time04 185.168 - time05 209.309 - } - } - kejimbase_action - { - entry - { - marker0 0.00 - marker1 42.585 - marker2 87.664 - } - exit - { - nextfile kejimbase_atr00 - nextmark marker0 - time00 69.347 - time01 72.142 - time02 80.444 - time03 87.608 - time04 90.185 - } - exit - { - nextfile kejimbase_atr01 - nextmark marker1 - time00 2.434 - time01 5.667 - time02 20.281 - } - exit - { - nextfile kejimbase_atr02 - nextmark marker2 - time00 62.894 - } - exit - { - nextfile kejimbase_atr03 - nextmark marker3 - time00 12.397 - time01 28.679 - time02 35.492 - time03 45.328 - } - } - ImpBaseB_Explore - { - entry - { - marker0 0 - marker1 37 - marker2 69.81 - marker3 119.97 - } - exit - { - nextfile ImpBaseB_Etr00 - time0 37 - time1 54.0 - time2 62.35 - time3 69.81 - time4 79.85 - time5 119.97 - time6 132.75 - time7 146.88 - } - exit - { - nextfile ImpBaseB_Etr01 - time0 13.67 - time1 26.96 - time2 89.42 - time3 96.92 - time4 107.77 - } - - } - ImpBaseB_Action - { - entry - { - marker0 0 - marker1 30.23 - marker2 45.45 - marker3 104.48 - } - exit - { - nextfile ImpBaseB_Atr00 - nextmark marker3 - time0 38.22 - time1 50.31 - time2 59.23 - time3 64.47 - time4 80.41 - time5 87.69 - time6 92.01 - time7 98.07 - time8 104.48 - } - exit - { - nextfile ImpBaseB_Atr01 - nextmark marker2 - time0 8.91 - time1 20.89 - } - exit - { - nextfile ImpBaseB_Atr02 - nextmark marker1 - time0 25.45 - time1 30.23 - } - exit - { - nextfile ImpBaseB_Atr03 - nextmark marker0 - time0 4.97 - time1 11.33 - time2 16.11 - time3 45.45 - time4 70.61 - time5 74.66 - } - } - ImpBaseC_explore - { - entry - { - marker0 0.000 - marker1 55.831 - marker2 11.160 - marker3 11.160 - - } - exit - { - nextfile ImpBaseC_etr00 - time00 42.904 - time01 71.172 - time02 127.721 - time03 150.290 - time04 171.618 - - } - exit - { - nextfile ImpBaseC_etr01 - time00 19.096 - time01 26.412 - time02 88.211 - time03 101.169 - - } - } - ImpBaseC_action - { - entry - { - marker0 0.00 - marker1 19.468 - marker2 33.480 - } - exit - { - nextfile ImpBaseC_atr00 - nextmark marker0 - time00 2.542 - time01 5.440 - time02 9.470 - time03 19.366 - } - exit - { - nextfile ImpBaseC_atr01 - nextmark marker1 - time00 25.544 - time01 29.140 - } - exit - { - nextfile ImpBaseC_atr02 - nextmark marker2 - time00 44.888 - } - exit - { - nextfile ImpBaseC_atr03 - nextmark marker3 - time00 34.272 - time01 65.224 - } - } - BespinA_Explore - { - entry - { - marker0 6.74 - marker1 17.51 - marker2 95.95 - marker3 149.87 - } - exit - { - nextfile BespinA_Etr00 - time00 42.01 - } - exit - { - nextfile BespinA_Etr01 - time00 165.65 - } - exit - { - nextfile BespinA_Etr02 - time00 17.51 - time01 29.50 - time02 54.80 - time03 70.21 - time04 90.25 - time05 106.40 - time06 120.53 - time07 149.87 - time08 178.36 - } - } - BespinA_Action - { - entry - { - marker0 0.00 - marker1 42.585 - marker2 87.664 - } - exit - { - nextfile BespinA_Atr00 - nextmark marker0 - time00 3.08 - time01 6.19 - time02 35.26 - } - exit - { - nextfile BespinA_Atr01 - nextmark marker1 - time00 8.98 - time01 14.76 - time02 20.65 - time03 44.34 - time04 47.28 - } - exit - { - nextfile BespinA_Atr02 - nextmark marker2 - time00 51.82 - time01 58.00 - } - exit - { - nextfile BespinA_Atr03 - nextmark marker3 - time00 28.90 - time01 64.78 - } - } - - besplat_explore - { - entry - { - marker0 46.78 - marker1 69.05 - marker2 85.85 - } - exit - { - nextfile besplat_etr00 - time0 6.89 - time1 21.26 - time3 55.52 - time4 69.75 - time5 85.87 - time6 98.12 - time7 119.44 - time8 131.95 - time9 157.58 - } - exit - { - nextfile besplat_etr01 - time0 34.15 - time1 141.84 - time2 174.72 - time3 183.05 - } - } - - besplat_action - { - entry - { - marker0 0 - marker1 16.56 - marker2 24.86 - marker3 62.37 - } - exit - { - nextfile besplat_atr00 - nextmark marker1 - time0 2.82 - time1 68.46 - } - exit - { - nextfile besplat_atr01 - nextmark marker2 - time0 41.23 - time1 54.20 - time2 59.31 - time3 76.51 - } - exit - { - nextfile besplat_atr02 - nextmark marker0 - time0 13.47 - time1 21.19 - time2 24.65 - time3 28.82 - time4 83.53 - } - } - - besplat_boss - { - } - - yavtrial_explore - { - entry - { - marker0 124.126 - marker1 102.326 - marker2 24.853 - marker3 0.00 - } - exit - { - nextfile yavtrial_etr00 - time00 3.095 - time01 23.931 - time02 24.937 - time03 46.905 - time04 61.268 - time05 79.042 - time06 101.750 - time07 118.136 - time08 147.951 - } - exit - { - nextfile yavtrial_etr01 - time00 161.783 - } - } - yavtrial_action - { - entry - { - marker0 0.00 - marker1 60.145 - marker2 85.922 - } - exit - { - nextfile yavtrial_atr00 - nextmark marker0 - time00 3.553 - time01 6.118 - time02 8.718 - time03 41.152 - time04 103.559 - } - exit - { - nextfile yavtrial_atr01 - nextmark marker1 - time00 9.307 - time01 12.310 - time02 16.719 - time03 20.045 - time04 26.229 - time05 35.160 - } - exit - { - nextfile yavtrial_atr02 - nextmark marker2 - time00 59.302 - time01 65.837 - time02 74.429 - } - exit - { - nextfile yavtrial_atr03 - nextmark marker3 - time00 38.325 - time01 49.857 - } - } - alienha_explore - { - entry - { - marker0 0 - marker1 65.84 - marker2 93.63 - } - exit - { - nextfile alienha_etr00 - time0 5.80 - time1 33.04 - time3 67.61 - } - exit - { - nextfile alienha_etr01 - time0 94.47 - time1 103.06 - time2 115.75 - time3 127.32 - time4 138.36 - time5 152.10 - time6 166.11 - time7 180.29 - } - } - alienha_action - { - entry - { - marker0 0 - marker1 40.96 - marker2 63.33 - } - exit - { - nextfile alienha_atr00 - nextmark marker2 - time0 3.35 - time1 6.85 - time3 15.70 - time4 22.61 - } - exit - { - nextfile alienha_atr01 - nextmark marker0 - time0 31.85 - time1 41.42 - time2 47.06 - } - exit - { - nextfile alienha_atr03 - nextmark marker1 - time0 53.01 - time1 58.57 - time2 62.87 - time3 72.03 - time4 89.64 - time5 96.94 - } - } - tunnels_explore - { - entry - { - marker0 0 - marker1 64.20 - marker2 96.47 - } - exit - { - nextfile tunnels_etr00 - time0 6.06 - time1 18.26 - time3 35.01 - time4 42.98 - time5 69.73 - time6 84.16 - } - exit - { - nextfile tunnels_etr01 - time0 94.81 - time1 111.25 - time2 121.77 - time3 134.68 - } - } - tunnels_action - { - entry - { - marker0 0 - marker1 22.39 - } - exit - { - nextfile tunnels_atr00 - nextmark marker0 - time0 0.29 - } - exit - { - nextfile tunnels_atr01 - nextmark marker2 - time0 15.62 - time1 22.94 - } - exit - { - nextfile tunnels_atr02 - nextmark marker2 - time0 29.14 - time1 35.63 - time2 45.33 - time3 51.78 - time4 58.67 - } - exit - { - nextfile tunnels_atr03 - nextmark marker1 - time0 64.81 - time1 68.53 - time2 72.28 - time3 75.89 - } - } - IMPBaseD_explore - { - entry - { - marker0 0.000 - marker1 66.790 - marker2 102.874 - marker3 150.554 - } - exit - { - nextfile IMPBaseD_etr00 - time00 7.997 - time01 16.678 - time02 44.664 - time03 70.836 - - } - exit - { - nextfile IMPBaseD_etr01 - time00 89.986 - time01 111.971 - time02 130.629 - time03 166.389 - time04 172.530 - } - } - IMPBaseD_action - { - entry - { - marker0 6.607 - marker1 60.118 - marker2 140.053 - } - exit - { - nextfile IMPBaseD_atr00 - nextmark marker0 - time00 6.457 - time01 13.265 - time02 18.757 - time03 25.194 - time04 152.772 - } - exit - { - nextfile IMPBaseD_atr01 - nextmark marker1 - time00 30.336 - time01 37.883 - time02 46.802 - time03 61.122 - } - exit - { - nextfile IMPBaseD_atr02 - nextmark marker2 - time00 78.257 - time01 85.312 - time02 92.170 - time03 140.866 - time04 149.597 - } - exit - { - nextfile IMPBaseD_atr03 - nextmark marker3 - time00 105.982 - time01 115.569 - time02 128.476 - } - } - swamp_explore - { - entry - { - marker0 0.000 - marker1 16.916 - marker2 80.714 - marker3 31.761 - - } - exit - { - nextfile swamp_etr00 - time00 11.185 - time01 20.989 - time02 51.408 - time03 63.196 - time04 71.293 - - } - exit - { - nextfile swamp_etr01 - time00 42.044 - time01 78.362 - time02 95.485 - time03 113.023 - - } - } - swamp_action - { - entry - { - marker0 0.00 - marker1 36.318 - marker2 45.982 - } - exit - { - nextfile swamp_atr00 - nextmark marker0 - time00 1.035 - } - exit - { - nextfile swamp_atr01 - nextmark marker1 - time00 6.835 - time01 11.323 - time02 18.592 - time03 36.230 - time04 59.793 - } - exit - { - nextfile swamp_atr02 - nextmark marker2 - time00 34.108 - time01 79.955 - time02 89.847 - time03 126.994 - - } - exit - { - nextfile swamp_atr03 - nextmark marker3 - time00 102.414 - time01 115.382 - time02 120.039 - } - } - yavtemp2_explore - { - entry - { - marker0 88.28 - marker1 48.10 - marker2 117.47 - marker3 0 - } - exit - { - nextfile yavtemp2_etr00 - time0 46.23 - time1 53.44 - time2 62.08 - time3 69.09 - time4 77.08 - time5 87.03 - time6 96.49 - } - exit - { - nextfile yavtemp2_etr01 - time0 15.24 - time1 31.79 - time2 42.78 - time3 114.18 - time4 134.25 - time5 144.89 - time6 160.03 - time7 168.03 - } - } - yavtemp2_action - { - entry - { - marker0 0 - marker1 17.35 - marker2 43.31 - marker3 60.39 - } - exit - { - nextfile yavtemp2_atr00 - nextmark marker0 - time0 0 - time1 8.78 - time2 13.47 - } - exit - { - nextfile yavtemp2_atr01 - nextmark marker1 - time0 23.89 - time1 28.62 - time2 41.11 - time3 46.73 - } - exit - { - nextfile yavtemp2_atr02 - nextmark marker2 - time0 48.95 - time1 60.59 - time2 69.13 - time3 97.63 - } - exit - { - nextfile yavtemp2_atr03 - nextmark marker3 - time0 91.11 - } - } - ImpBaseE_explore - { - entry - { - marker0 0.000 - marker1 13.805 - marker2 29.265 - marker3 137.915 - - } - exit - { - nextfile ImpBaseE_etr00 - time00 13.712 - time01 37.872 - time02 52.541 - time03 131.875 - time04 232.256 - - } - exit - { - nextfile ImpBaseE_etr01 - time00 120.057 - time01 157.080 - time02 176.388 - - } - } - ImpBaseE_action - { - entry - { - marker0 0.00 - marker1 18.336 - marker2 52.491 - } - exit - { - nextfile ImpBaseE_atr00 - nextmark marker0 - time00 22.012 - time01 32.861 - time02 73.853 - time03 77.808 - } - exit - { - nextfile ImpBaseE_atr01 - nextmark marker1 - time00 5.824 - time01 18.457 - time02 81.088 - time03 114.805 - } - exit - { - nextfile ImpBaseE_atr02 - nextmark marker2 - time00 1.923 - time01 26.892 - time02 30.703 - time03 59.294 - time04 65.331 - time05 88.803 - time06 91.876 - - } - exit - { - nextfile ImpBaseE_atr03 - nextmark marker3 - time00 11.958 - time01 43.027 - time02 48.014 - time04 96.757 - time05 107.858 - time06 130.437 - } - } - alienhb_explore - { - entry - { - marker0 127.71 - marker1 36.56 - marker2 89.94 - } - exit - { - nextfile alienhb_etr00 - time0 13.60 - time1 22.58 - time3 31.69 - time4 41.08 - time5 53.08 - time6 67.91 - time7 89.29 - time8 181.41 - } - exit - { - nextfile alienhb_etr01 - time0 109.08 - time1 123.18 - time2 134.76 - time3 149.54 - time4 160.53 - time5 174.10 - } - } - alienhb_action - { - entry - { - marker0 0 - marker1 6.85 - marker2 31.84 - marker3 66.77 - } - exit - { - nextfile alienhb_atr00 - nextmark marker0 - time0 5.29 - time1 21.54 - time3 26.21 - time4 120.30 - } - exit - { - nextfile alienhb_atr01 - nextmark marker1 - time0 10.35 - time1 17.03 - } - exit - { - nextfile alienhb_atr02 - nextmark marker2 - time0 60.27 - time1 70.21 - time2 80.36 - time3 93.55 - time4 100.47 - time5 111.75 - } - } - yavfinal_explore - { - entry - { - marker0 0.000 - marker1 18.664 - marker2 53.390 - marker3 97.161 - - } - exit - { - nextfile yavfinal_etr00 - time00 53.434 - time01 83.935 - - } - exit - { - nextfile yavfinal_etr01 - time00 9.852 - time01 94.171 - time02 104.106 - - } - } - yavfinal_action - { - entry - { - marker0 0.00 - marker1 43.094 - marker2 73.785 - } - exit - { - nextfile yavfinal_atr00 - nextmark marker0 - time00 53.502 - time01 61.386 - } - exit - { - nextfile yavfinal_atr01 - nextmark marker1 - time00 3.623 - time01 96.341 - } - exit - { - nextfile yavfinal_atr02 - nextmark marker2 - time00 9.019 - time01 11.707 - time02 15.535 - time03 29.107 - time04 35.847 - time05 75.327 - time06 101.992 - - } - exit - { - nextfile yavfinal_atr03 - nextmark marker3 - time00 21.257 - time01 25.167 - time02 43.800 - time03 106.249 - time04 113.638 - - } - } - yavfinal_boss - { - } - narshaada_explore - { - entry - { - marker0 123.18 - marker1 0 - marker2 43.30 - marker3 12.27 - } - exit - { - nextfile narshaada_etr00 - time0 55.86 - time1 70.17 - time2 78.63 - time3 88.61 - time4 106.57 - - } - exit - { - nextfile narshaada_etr01 - time0 13.75 - time1 31.29 - time2 43.84 - time4 123.91 - time5 134.92 - time6 149.29 - time7 168.16 - time8 184.19 - } - } - narshaada_action - { - entry - { - marker0 0 - marker1 15.65 - marker2 47.07 - } - exit - { - nextfile narshaada_atr00 - nextmark marker0 - time0 2.72 - time1 59.84 - time2 63.90 - time3 74.16 - time4 82.37 - } - exit - { - nextfile narshaada_atr01 - nextmark marker1 - time0 10.89 - time1 20.59 - time2 28.15 - time3 39.65 - time4 46.35 - } - exit - { - nextfile narshaada_atr02 - nextmark marker2 - time0 48.98 - time1 69.05 - } - exit - { - nextfile narshaada_atr03 - nextmark marker3 - time0 86.14 - time1 90.73 - time2 96.40 - time3 101.09 - } - } - -} -levelmusic -{ - kejim_post - { - explore ImpBaseB_Explore - action ImpBaseB_Action - } - kejim_base - { - explore kejimbase_explore - action kejimbase_action - } - artus_mine - { - explore tunnels_explore - action tunnels_action - } - artus_detention - { - explore ImpBaseC_explore - action ImpBaseC_action - useboss bespin_platform - } - artus_topside - { - explore ImpBaseD_explore - action ImpBaseD_action - } - ns_streets - { - explore narshaada_explore - action narshaada_action - } - ns_hideout - { - explore alienha_explore - action alienha_action - } - ns_starpad - { - explore alienhb_explore - action alienhb_action - } - bespin_undercity - { - uses artus_mine - } - bespin_streets - { - explore BespinA_Explore - action BespinA_Action - } - bespin_platform - { - explore besplat_explore - action besplat_action - boss besplat_boss - } - cairn_bay - { - explore ImpBaseE_explore - action ImpBaseE_action - } - cairn_dock1 - { - uses kejim_base - } - cairn_assembly - { - uses kejim_post - } - cairn_stockpile - { - uses artus_detention - } - cairn_reactor - { - uses artus_topside - } - cairn_dock2 - { - uses cairn_bay - } - demo - { - uses kejim_post - useboss bespin_platform - } - doom_comm - { - uses kejim_base - } - doom_detention - { - uses kejim_post - } - doom_shields - { - uses artus_detention - } - yavin_swamp - { - explore swamp_explore - action swamp_action - } - yavin_canyon - { - uses ns_hideout - } - yavin_courtyard - { - explore yavtemp2_explore - action yavtemp2_action - } - yavin_final - { - explore yavfinal_explore - action yavfinal_action - boss yavfinal_boss - } - yavin_temple - { - explore placeholder - action placeholder - } - yavin_trial - { - explore yavtrial_explore - action yavtrial_action - } -} diff --git a/code/base/ext_data/items.dat b/code/base/ext_data/items.dat deleted file mode 100644 index 41d9e7c5..00000000 --- a/code/base/ext_data/items.dat +++ /dev/null @@ -1,712 +0,0 @@ -// EXTERNAL ITEM DATA -// - -//Fields -//pickupsound STRING; DEFAULT = sound/weapons/w_pkup.wav -//itemname STRING; -//classname STRING; -//count INT; ammount of ammo or health given with item -//icon STRING; -//min VECTOR; item bounds min, DEFAULT = -16 -16 -2 -//max VECTOR; item bounds max, DEFAULT = 16 16 16 -//pickupname STRING; name to show in inventory -//tag ENUM; WP_, or AMMO_ -//type ENUM; IT_WEAPON, IT_AMMO, IT_ARMOR, IT_HEALTH -//worldmodel STRING; model to show on ground or in hand - -{ -itemname ITM_SABER_PICKUP - -classname weapon_saber -worldmodel models/weapons2/saber/saber_w.md3 -icon gfx/hud/w_icon_lightsaber -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_SABER -min -16 -16 -8 -max 16 16 16 -} - - -{ -itemname ITM_BRYAR_PISTOL_PICKUP - -classname weapon_bryar_pistol -worldmodel models/weapons2/briar_pistol/briar_pistol_w.glm -icon gfx/hud/w_icon_briar -// Amount of ammo given with weapon -count 10 -type IT_WEAPON -tag WP_BRYAR_PISTOL -min -10 -10 -2 -max 10 10 12 -} - - -{ -itemname ITM_BLASTER_PICKUP - -classname weapon_blaster -worldmodel models/weapons2/blaster_r/blaster_w.glm -icon gfx/hud/w_icon_blaster -// Amount of ammo given with weapon -count 10 -type IT_WEAPON -tag WP_BLASTER -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_DISRUPTOR_PICKUP - -classname weapon_disruptor -worldmodel models/weapons2/disruptor/disruptor_w.glm -icon gfx/hud/w_icon_disruptor -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_DISRUPTOR -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_BOWCASTER_PICKUP - -classname weapon_bowcaster -worldmodel models/weapons2/bowcaster/bowcaster_w.glm -icon gfx/hud/w_icon_bowcaster -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_BOWCASTER -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_REPEATER_PICKUP - -classname weapon_repeater -worldmodel models/weapons2/heavy_repeater/heavy_repeater_w.glm -icon gfx/hud/w_icon_repeater -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_REPEATER -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_DEMP2_PICKUP - -classname weapon_demp2 -worldmodel models/weapons2/demp2/demp2_w.glm -icon gfx/hud/w_icon_demp2 -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_DEMP2 -min -10 -10 -2 -max 10 10 12 -} - - -{ -itemname ITM_FLECHETTE_PICKUP - -classname weapon_flechette -worldmodel models/weapons2/golan_arms/golan_arms_w.glm -icon gfx/hud/w_icon_flechette -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_FLECHETTE -min -10 -10 -2 -max 10 10 12 -} - - -{ -itemname ITM_ROCKET_LAUNCHER_PICKUP - -classname weapon_rocket_launcher -worldmodel models/weapons2/merr_sonn/merr_sonn_w.glm -icon gfx/hud/w_icon_merrsonn -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_ROCKET_LAUNCHER -min -10 -10 -2 -max 10 10 12 -} - - -{ -itemname ITM_THERMAL_DET_PICKUP - -classname weapon_thermal -worldmodel models/weapons2/thermal/thermal_pu.md3 -icon gfx/hud/w_icon_thermal -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_THERMAL -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_TRIP_MINE_PICKUP - -classname weapon_trip_mine -worldmodel models/weapons2/laser_trap/laser_trap_pu.md3 -icon gfx/hud/w_icon_tripmine -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_TRIP_MINE -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_DET_PACK_PICKUP - -classname weapon_det_pack -worldmodel models/weapons2/detpack/det_pack_pu.md3 -icon gfx/hud/w_icon_detpack -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_DET_PACK -min -10 -10 -2 -max 10 10 12 -} - -{ -itemname ITM_STUN_BATON_PICKUP - -classname weapon_stun_baton -worldmodel models/weapons2/stun_baton/stunbaton_w.glm -icon gfx/hud/w_icon_stunbaton -// Amount of ammo given with weapon -count 50 -type IT_WEAPON -tag WP_STUN_BATON -} - - -{ -itemname ITM_BOT_LASER_PICKUP - -classname weapon_botwelder -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_BOT_LASER -} - -{ -itemname ITM_MELEE - -classname weapon_melee -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_MELEE -min -16 -16 -2 -max 16 16 16 -} - -{ -itemname ITM_EMPLACED_GUN_PICKUP - -classname weapon_emplaced_gun -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 800 -type IT_WEAPON -tag WP_EMPLACED_GUN -} - -{ -itemname ITM_TURRET_PICKUP - -classname weapon_turret -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_TURRET -} - -{ -itemname ITM_ATST_MAIN_PICKUP - -classname weapon_atst_main -worldmodel models/weapons2/noweap/noweap.md3 -icon gfx/hud/w_icon_atst -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_ATST_MAIN -} - -{ -itemname ITM_ATST_SIDE_PICKUP - -classname weapon_atst_side -worldmodel models/weapons2/noweap/noweap.md3 -icon gfx/hud/w_icon_atstside -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_ATST_SIDE -} - -{ -itemname ITM_TIE_FIGHTER_PICKUP - -classname weapon_tie_fighter -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_TIE_FIGHTER -} - -{ -itemname ITM_RAPID_FIRE_CONC_PICKUP - -classname weapon_rapid_concussion -worldmodel models/weapons2/noweap/noweap.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_RAPID_FIRE_CONC -} - -{ -itemname ITM_BLASTER_PISTOL_PICKUP - -classname weapon_blaster_pistol -worldmodel models/weapons2/imp_pistol/pistol_w.md3 -// Amount of ammo given with weapon -count 400 -type IT_WEAPON -tag WP_BLASTER_PISTOL -} - -// -//Items -// - -// AMMO Items -//------------- -{ -itemname ITM_AMMO_FORCE_PICKUP - -classname ammo_force -worldmodel models/items/forcegem.md3 -pickupsound sound/player/enlightenment.wav -icon gfx/hud/forcegem_icon2 -count 100 -type IT_AMMO -tag AMMO_FORCE -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_BLASTER_PICKUP - -classname ammo_blaster -worldmodel models/items/energy_cell.md3 -icon gfx/hud/energy_cell -count 25 -type IT_AMMO -tag AMMO_BLASTER -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_POWERCELL_PICKUP - -classname ammo_powercell -worldmodel models/items/power_cell.md3 -icon gfx/hud/power_cell -count 100 -type IT_AMMO -tag AMMO_POWERCELL -max 8 8 16 -min -8 -8 -0 -} - - -{ -itemname ITM_AMMO_METAL_BOLTS_PICKUP - -classname ammo_metallic_bolts -worldmodel models/items/metallic_bolts.md3 -icon gfx/hud/metallic_bolts -count 100 -type IT_AMMO -tag AMMO_METAL_BOLTS -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_ROCKETS_PICKUP - -classname ammo_rockets -worldmodel models/items/rockets.md3 -icon gfx/hud/rockets -count 3 -type IT_AMMO -tag AMMO_ROCKETS -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_EMPLACED_PICKUP - -classname ammo_emplaced -worldmodel models/weapons2/noweap/noweap.md3 -count 100 -type IT_AMMO -tag AMMO_EMPLACED -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_THERMAL_PICKUP - -classname ammo_thermal -worldmodel models/weapons2/thermal/thermal_pu.md3 -icon gfx/hud/w_icon_thermal -count 4 -type IT_AMMO -tag AMMO_THERMAL -max 16 16 16 -min -16 -16 -0 -} - -{ -itemname ITM_AMMO_TRIPMINE_PICKUP - -classname ammo_tripmine -worldmodel models/weapons2/laser_trap/laser_trap_pu.md3 -icon gfx/hud/w_icon_tripmine -count 3 -type IT_AMMO -tag AMMO_TRIPMINE -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_AMMO_DETPACK_PICKUP - -classname ammo_detpack -worldmodel models/weapons2/detpack/det_pack_pu.md3 -icon gfx/hud/w_icon_detpack -count 3 -type IT_AMMO -tag AMMO_DETPACK -max 8 8 16 -min -8 -8 -0 -} - - - -{ -itemname ITM_BATTERY_PICKUP - -classname item_battery -worldmodel models/items/battery.md3 -icon gfx/hud/battery -count 1000 -type IT_BATTERY -tag ITM_BATTERY_PICKUP -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_SEEKER_PICKUP -classname item_seeker -worldmodel models/items/remote.md3 -icon gfx/hud/i_icon_seeker -count 120 -type IT_HOLDABLE -tag INV_SEEKER -max 8 8 16 -min -8 -8 -4 -} - -{ -itemname ITM_SHIELD_PICKUP -classname item_enviro -worldmodel models/items/shield.md3 -icon gfx/hud/i_icon_shieldwall -count 100 -type IT_HOLDABLE -tag ITM_SHIELD_PICKUP -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_BACTA_PICKUP -classname item_bacta -worldmodel models/items/bacta.md3 -icon gfx/hud/i_icon_bacta -count 25 -type IT_HOLDABLE -tag INV_BACTA_CANISTER -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_DATAPAD_PICKUP -classname item_datapad -worldmodel models/items/datapad.md3 -count 1 -type IT_HOLDABLE -tag ITM_DATAPAD_PICKUP -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_BINOCULARS_PICKUP -classname item_binoculars -worldmodel models/items/binoculars.md3 -icon gfx/hud/i_icon_zoom -count 1 -type IT_HOLDABLE -tag INV_ELECTROBINOCULARS -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_SENTRY_GUN_PICKUP -classname item_sentry_gun -worldmodel models/items/psgun.glm -icon gfx/hud/i_icon_sentrygun -count 120 -type IT_HOLDABLE -tag INV_SENTRY -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_LA_GOGGLES_PICKUP -classname item_la_goggles -worldmodel models/items/binoculars.md3 -icon gfx/hud/i_icon_goggles -count 30 -type IT_HOLDABLE -tag INV_LIGHTAMP_GOGGLES -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_MEDPAK_PICKUP -classname item_medpak_instant -worldmodel models/items/medpac.md3 -icon gfx/hud/i_icon_medkit -count 20 -type IT_HEALTH -tag ITM_MEDPAK_PICKUP -max 8 8 16 -min -8 -8 -4 -} - -{ -itemname ITM_SHIELD_SM_PICKUP -classname item_shield_sm_instant -worldmodel models/items/psd_sm.md3 -icon gfx/hud/psd_small -count 25 -type IT_ARMOR -tag ITM_SHIELD_SM_PICKUP -max 8 8 16 -min -8 -8 -4 -} - -{ -itemname ITM_SHIELD_LRG_PICKUP -classname item_shield_lrg_instant -worldmodel models/items/psd.md3 -icon gfx/hud/psd_medium -count 50 -type IT_ARMOR -tag ITM_SHIELD_LRG_PICKUP -max 8 8 16 -min -8 -8 -4 -} - - -{ -itemname ITM_GOODIE_KEY_PICKUP -classname item_goodie_key -worldmodel models/items/key.md3 -icon gfx/hud/i_icon_goodie_key -type IT_HOLDABLE -tag INV_GOODIE_KEY -max 8 8 16 -min -8 -8 -0 -} - - -{ -itemname ITM_SECURITY_KEY_PICKUP -classname item_security_key -worldmodel models/items/key.md3 -icon gfx/hud/i_icon_security_key -type IT_HOLDABLE -tag INV_SECURITY_KEY -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_HEAL_PICKUP - -classname holocron_force_heal -worldmodel models/map_objects/force_holocrons/heal.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_heal -count 1 -type IT_HOLOCRON -tag FP_HEAL -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_LEVITATION_PICKUP - -classname holocron_force_levitation -worldmodel models/map_objects/force_holocrons/jump.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_levitation -count 1 -type IT_HOLOCRON -tag FP_LEVITATION -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_SPEED_PICKUP - -classname holocron_force_speed -worldmodel models/map_objects/force_holocrons/speed.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_speed -count 1 -type IT_HOLOCRON -tag FP_SPEED -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_PUSH_PICKUP - -classname holocron_force_push -worldmodel models/map_objects/force_holocrons/push.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_push -count 1 -type IT_HOLOCRON -tag FP_PUSH -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_PULL_PICKUP - -classname holocron_force_pull -worldmodel models/map_objects/force_holocrons/pull.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_pull -count 1 -type IT_HOLOCRON -tag FP_PULL -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_TELEPATHY_PICKUP - -classname holocron_force_telepathy -worldmodel models/map_objects/force_holocrons/telepathy.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_telepathy -count 1 -type IT_HOLOCRON -tag FP_TELEPATHY -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_GRIP_PICKUP - -classname holocron_force_grip -worldmodel models/map_objects/force_holocrons/grip.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_grip -count 1 -type IT_HOLOCRON -tag FP_GRIP -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_LIGHTNING_PICKUP - -classname holocron_force_lightning -worldmodel models/map_objects/force_holocrons/lightning.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_lightning -count 1 -type IT_HOLOCRON -tag FP_LIGHTNING -max 8 8 16 -min -8 -8 -0 -} - -{ -itemname ITM_FORCE_SABERTHROW_PICKUP - -classname holocron_force_saberthrow -worldmodel models/map_objects/force_holocrons/saberthrow.md3 -pickupsound sound/player/holocron.wav -icon gfx/hud/f_icon_saberthrow -count 1 -type IT_HOLOCRON -tag FP_SABERTHROW -max 8 8 16 -min -8 -8 -0 -} diff --git a/code/base/ext_data/weapons.dat b/code/base/ext_data/weapons.dat deleted file mode 100644 index 79537995..00000000 --- a/code/base/ext_data/weapons.dat +++ /dev/null @@ -1,629 +0,0 @@ -// EXTERNAL WEAPON & AMMO DATA -// -// NOTE!!!!!!!!! Weapontype must start the block of weapon data. -// NOTE!!!!!!!!! Ammo must start the block of ammo data. -// -// Weapontype - weapon data is associated with which weapon (must be first) -// WP_NONE -// WP_PHASER -// WP_COMPRESSION_RIFLE -// WP_IMOD -// WP_SCAVENGER_RIFLE -// WP_STASIS -// WP_GRENADE_LAUNCHER, -// WP_TETRION_DISRUPTOR, -// WP_DREADNOUGHT, -// WP_QUANTUM_BURST, -// WP_BORG_WEAPON -// WP_BORG_TASER -// WP_BORG_ASSIMILATOR -// WP_BORG_DRILL -// WP_TRICORDER -// -// Weaponclass - weapon name -// Weaponmodel - weapon model used in game -// weaponicon - interface image -// Ammotype - type of power weapon needs to fire -// 0 - No power -// 1 - Star Fleet power -// 2 - Alien Crystal power -// 3 - Phaser power -// Ammolowcount - amount when "Low ammo" warning appears on screen -// Flashcolor - color generate by weapon flash (R,G,B) -// Firingsound - sound file used when firing -// altfiringsound - sound file used when alt-firing -// flashsound - sound file used by flash -// altflashsound - sound file used by an alt-fire flash -// stopsound - sound file used when a firing sound stops -// Firetime - amount of time between firings -// altfireTime - for alt fire -// Range - range of weapon -// energyPerShot - amount of energy used per shot -// altenergypershot- for alt fire -// barrelcount - number of barrels the model has (weaponname_b?.md3) -// missileModel - missile .md3 -// altmissileModel - alternate missile .md3 -// missileSound - played while flying -// altmissileSound - alternate missile launch sound -// missileLight - intensity of lightsource for missile - if 0.0 then none (float) -// altmissileLight - alternate missile light -// missileLightColor - color in three float style R, G, B (0.0 to 1.0) - NOTE - if you have a light, you MUST HAVE THESE -// altmissileLightColor - alternate color in three float style R, G, B (0.0 to 1.0) -// missileHitSound - played on impact -// altmissileHitSound - for alt fire -// missileFuncName - missile fly function -// altmissileFuncName - for alt fire -// -// FUNCTION NAMES -// borgfunc -// scavengerfunc -// altscavengerfunc -// stasisfunc -// grenadefunc -// altgrenadefunc -// tetrionfunc -// dreadnoughtfunc -// quantumfunc -// quantumaltfunc -// botrocketfunc -// forgeprojfunc -// forgeprojfunc2 -// forgepsychfunc -// parasiteacidfunc -// stasisattackfunc -// loaderlaserfunc -// botprojfunc - -// -// For AMMO Types -// ammoicon - STRING -// ammomax - INT - - -// WP_NULL -{ -WEAPONTYPE WP_NONE -} - -// WP_STUN_BATON -{ -weapontype WP_STUN_BATON -weaponclass weapon_stun_baton -weaponmodel models/weapons2/stun_baton/baton.md3 -weaponIcon gfx/hud/w_icon_stunbaton -firingsound sound/weapons/baton/idle.wav -firingforce fffx/weapons/baton/idle -barrelcount 3 -ammotype 1 -ammolowcount 5 -energypershot 0 -firetime 400 -range 8192 -altenergypershot 0 -altfiretime 400 -altrange 8192 -} - -// WP_SABER -{ -weapontype WP_SABER -weaponclass weapon_saber -weaponmodel models/weapons2/saber/saber_w.md3 -weaponIcon gfx/hud/w_icon_lightsaber -firingsound sound/weapons/saber/saberhum1.wav -ammotype 1 -ammolowcount 5 -energypershot 1 -firetime 100 -range 8192 -altenergypershot 3 -altfiretime 100 -altrange 8192 -missilemodel models/weapons2/saber/saber_w.md3 -} - - -// WP_BRYAR_PISTOL -{ -weapontype WP_BRYAR_PISTOL -weaponclass weapon_bryar_pistol -weaponmodel models/weapons2/briar_pistol/briar_pistol.md3 -weaponIcon gfx/hud/w_icon_briar -missileFuncName bryar_func -altmissileFuncName bryar_alt_func -ammotype 2 -ammolowcount 15 -energypershot 1 -firetime 400 -range 8192 -altenergypershot 1 -altfiretime 400 -altrange 8192 -muzzleEffect bryar/muzzle_flash -altmuzzleEffect bryar/altmuzzle_flash -altchargesound sound/weapons/bryar/altcharge.wav -altchargeforce fffx/weapons/bryar/altcharge -selectSound sound/weapons/bryar/select.wav -selectforce fffx/weapons/bryar/select -} - -// WP_BLASTER -{ -weapontype WP_BLASTER -weaponclass weapon_blaster -weaponmodel models/weapons2/blaster_r/blaster.md3 -weaponIcon gfx/hud/w_icon_blaster -ammotype 2 -ammolowcount 15 -energypershot 1 -firetime 350 -range 8192 -altenergypershot 2 -altfiretime 150 -altrange 8192 -missileFuncName blaster_func -altmissileFuncName blaster_alt_func -muzzleEffect blaster/muzzle_flash -altmuzzleEffect blaster/altmuzzle_flash -selectSound sound/weapons/blaster/select.wav -selectforce fffx/weapons/blaster/select -} - -// WP_DISRUPTOR -{ -weapontype WP_DISRUPTOR -weaponclass weapon_disruptor -weaponmodel models/weapons2/disruptor/disruptor.md3 -weaponIcon gfx/hud/w_icon_disruptor -ammotype 3 -ammolowcount 15 -energypershot 3 -barrelcount 1 -firetime 600 -range 8192 -altenergypershot 3 -altfiretime 1300 -altrange 8192 -muzzleEffect disruptor/muzzle_flash -altmuzzleEffect disruptor/altmuzzle_flash -selectSound sound/weapons/disruptor/select.wav -selectforce fffx/weapons/disruptor/select -altchargesound sound/weapons/disruptor/altCharge.wav -altchargeforce fffx/weapons/disruptor/altcharge -} - -// WP_BOWCASTER -{ -weapontype WP_BOWCASTER -weaponclass weapon_bowcaster -weaponmodel models/weapons2/bowcaster/bowcaster.md3 -weaponIcon gfx/hud/w_icon_bowcaster -altchargesound sound/weapons/bowcaster/altcharge.wav -altchargeforce fffx/weapons/bowcaster/altcharge -ammotype 3 -ammolowcount 15 -energypershot 5 -firetime 750 -range 8192 -altenergypershot 5 -altfiretime 400 -altrange 8192 -missileFuncName bowcaster_func -altmissileFuncName bowcaster_func -muzzleEffect bowcaster/muzzle_flash -altmuzzleEffect bowcaster/altmuzzle_flash -selectSound sound/weapons/bowcaster/select.wav -selectforce fffx/weapons/bowcaster/select -chargesound sound/weapons/bowcaster/altcharge.wav -chargeforce fffx/weapons/bowcaster/altcharge -} - -// WP_REPEATER -{ -weapontype WP_REPEATER -weaponclass weapon_repeater -weaponmodel models/weapons2/heavy_repeater/heavy_repeater.md3 -weaponIcon gfx/hud/w_icon_repeater -ammotype 4 -ammolowcount 25 -energypershot 1 -firetime 50 -range 8192 -altenergypershot 8 -altfiretime 800 -altrange 8192 -barrelcount 1 -missileFuncName repeater_func -altmissileFuncName repeater_alt_func -muzzleEffect repeater/muzzle_flash -altmuzzleEffect repeater/altmuzzle_flash -selectSound sound/weapons/repeater/select.wav -selectforce fffx/weapons/repeater/select -} - -// WP_DEMP2 -{ -weapontype WP_DEMP2 -weaponclass weapon_demp2 -weaponmodel models/weapons2/demp2/demp2.md3 -weaponIcon gfx/hud/w_icon_demp2 -ammotype 3 -ammolowcount 15 -energypershot 8 -firetime 450 -range 8192 -altenergypershot 10 -altfiretime 1200 -altrange 8192 -missileFuncName demp2_func -muzzleEffect demp2/muzzle_flash -altmissileFuncName demp2_alt_func -altmuzzleEffect demp2/altmuzzle_flash -selectSound sound/weapons/demp2/select.wav -selectforce fffx/weapons/demp2/select -altchargesound sound/weapons/demp2/altCharge.wav -altchargeforce fffx/weapons/demp2/altcharge -} - - -// WP_FLECHETTE -{ -weapontype WP_FLECHETTE -weaponclass weapon_flechette -weaponmodel models/weapons2/golan_arms/golan_arms.md3 -barrelcount 1 -ammotype 4 -ammolowcount 15 -firetime 550 -energypershot 8 -range 8192 -weaponIcon gfx/hud/w_icon_flechette -altenergypershot 8 -altfiretime 400 -altrange 8192 -missileFuncName flechette_func -missileModel models/weapons2/golan_arms/projectileMain.md3 -altmissileFuncName flechette_alt_func -muzzleEffect flechette/muzzle_flash -altmuzzleEffect flechette/altmuzzle_flash -altmissileModel models/weapons2/golan_arms/projectile.md3 -selectSound sound/weapons/flechette/select.wav -selectforce fffx/weapons/flechette/select -} - -// WP_ROCKET_LAUNCHER -{ -weapontype WP_ROCKET_LAUNCHER -weaponclass weapon_rocket_launcher -weaponmodel models/weapons2/merr_sonn/merr_sonn.md3 -ammotype 5 -ammolowcount 1 -firetime 600 -energypershot 1 -range 8192 -weaponIcon gfx/hud/w_icon_merrsonn -barrelcount 1 -altenergypershot 1 -altfiretime 1000 -altrange 8192 -missileLight 125 -missileLightColor 1.0 1.0 0.5 -altmissileLight 125 -altmissileLightColor 1.0 1.0 0.5 -missileFuncName rocket_func -altmissileFuncName rocket_alt_func -muzzleEffect rocket/muzzle_flash2 -altmuzzleEffect rocket/altmuzzle_flash -missileModel models/weapons2/merr_sonn/projectile.md3 -altmissileModel models/weapons2/merr_sonn/projectile.md3 -missilesound sound/weapons/rocket/missleloop.wav -altmissilesound sound/weapons/rocket/missleloop.wav -selectSound sound/weapons/rocket/select.wav -selectforce fffx/weapons/rocket/select -} - - -// WP_THERMAL -{ -weapontype WP_THERMAL -weaponclass weapon_thermal -weaponmodel models/weapons2/thermal/thermal.md3 -weaponIcon gfx/hud/w_icon_thermal -ammotype 7 -ammolowcount 1 -energypershot 1 -firetime 800 -range 8192 -altenergypershot 1 -altfiretime 400 -altrange 8192 -missileModel models/weapons2/thermal/thermal_proj.md3 -altmissileModel models/weapons2/thermal/thermal_proj.md3 -barrelcount 0 -chargesound sound/weapons/thermal/charge.wav -chargeforce fffx/weapons/thermal/charge -altchargesound sound/weapons/thermal/charge.wav -altchargeforce fffx/weapons/thermal/charge -selectSound sound/weapons/thermal/select.wav -selectforce fffx/weapons/thermal/select -muzzleEffect thermal/muzzle_flash -} - -// WP_TRIP_MINE -{ -weapontype WP_TRIP_MINE -weaponclass weapon_trip_mine -weaponmodel models/weapons2/laser_trap/laser_trap.md3 -weaponIcon gfx/hud/w_icon_tripmine -ammotype 8 -ammolowcount 1 -energypershot 1 -firetime 800 -range 8192 -altenergypershot 1 -altfiretime 400 -altrange 8192 -missileModel models/weapons2/laser_trap/laser_trap_w.glm -altmissileModel models/weapons2/laser_trap/laser_trap_w.glm -selectSound sound/weapons/detpack/select.wav -selectforce fffx/weapons/detpack/select -muzzleEffect tripmine/muzzle_flash - -} - -// WP_DET_PACK -{ -weapontype WP_DET_PACK -weaponclass weapon_det_pack -weaponmodel models/weapons2/detpack/det_pack.md3 -weaponIcon gfx/hud/w_icon_detpack -ammotype 9 -ammolowcount 1 -energypershot 1 -firetime 800 -range 8192 -altenergypershot 0 -altfiretime 400 -altrange 8192 -missileModel models/weapons2/detpack/det_pack_proj.glm -selectSound sound/weapons/detpack/select.wav -selectforce fffx/weapons/detpack/select -muzzleEffect detpack/muzzle_flash -} - -// WP_EMPLACED_GUN -{ -weapontype WP_EMPLACED_GUN -weaponclass weapon_emplaced_gun -weaponmodel models/weapons2/noweap/noweap.md3 - -altenergypershot 1 -altrange 8192 -missileFuncName emplaced_func -altmissileFuncName emplaced_func -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 150 -altfiretime 150 -range 8192 -muzzleEffect emplaced/muzzle_flash -} - -// WP_BOT_LASER -{ -weapontype WP_BOT_LASER -weaponclass weapon_bryar_pistol -weaponmodel models/weapons2/noweap/noweap.md3 - -//flashsound sound/weapons/probe/fire.wav -//altflashsound sound/weapons/probe/alt_fire.wav -altenergypershot 0 -altrange 8192 -missileFuncName bryar_func -ammotype 1 -ammolowcount 15 -energypershot 2 -firetime 1600 -range 8192 -} - -// WP_MELEE -{ -weapontype WP_MELEE -weaponclass weapon_melee -weaponmodel models/weapons2/noweap/noweap.md3 - -ammotype 3 -ammolowcount 5 -energypershot 0 -firetime 1000 -range 1024 -} - -// WP_ATST_MAIN -{ -weapontype WP_ATST_MAIN -weaponclass weapon_atst_main -weaponmodel models/weapons2/noweap/noweap.md3 -weaponIcon gfx/hud/w_icon_atst -//flashsound sound/weapons/atst/ATSTfire1.wav -//altflashsound sound/weapons/atst/ATSTfire2.wav -altenergypershot 1 -altrange 8192 -missileFuncName atstmain_func -altmissileFuncName atstmain_func -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 200 -altfiretime 150 -range 8192 -muzzleEffect emplaced/muzzle_flash -} - -// WP_ATST_SIDE -{ -weapontype WP_ATST_SIDE -weaponclass weapon_atst_side -weaponmodel models/weapons2/noweap/noweap.md3 -weaponIcon gfx/hud/w_icon_atstside -//flashsound sound/weapons/atst/ATSTfire3.wav -//altflashsound sound/weapons/atst/ATSTfire4.wav -altenergypershot 1 -altrange 8192 - -altmissileModel models/weapons2/merr_sonn/projectile.md3 - -missileFuncName atst_side_main_func -altmissileFuncName atst_side_alt_func -muzzleEffect emplaced/muzzle_flash -altmuzzleEffect emplaced/muzzle_flash - -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 400 -altfiretime 1000 -range 8192 -} - -// WP_TIE_FIGHTER -{ -weapontype WP_TIE_FIGHTER -weaponclass weapon_tie_fighter -weaponmodel models/weapons2/noweap/noweap.md3 -weaponIcon icons/w_icon_tie -//flashsound sound/weapons/tie_fighter/tie_fire.wav -//altflashsound sound/weapons/tie_fighter/tie_fire2.wav -altenergypershot 1 -altrange 8192 -missileFuncName emplaced_func -altmissileFuncName emplaced_func -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 400 -altfiretime 400 -range 8192 -muzzleEffect emplaced/muzzle_flash -} - -// WP_RAPID_FIRE_CONC -{ -weapontype WP_RAPID_FIRE_CONC -weaponclass weapon_radid_concussion -weaponmodel models/weapons2/noweap/noweap.md3 -weaponIcon icons/w_icon_tie -//flashsound sound/weapons/rapid_conc/fire.wav -//altflashsound sound/weapons/rapid_conc/alt_fire.wav -altenergypershot 1 -altrange 8192 -missileFuncName emplaced_func -altmissileFuncName repeater_alt_func -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 400 -altfiretime 1000 -range 8192 -muzzleEffect emplaced/muzzle_flash -} - -// WP_BLASTER_PISTOL -{ -weapontype WP_BLASTER_PISTOL -weaponclass weapon_blaster_pistol -weaponmodel models/weapons2/imp_pistol/pistol.md3 - -//flashsound sound/weapons/npc_blaster/fire.wav -//altflashsound sound/weapons/npc_blaster/alt_fire.wav -missileFuncName bryar_func -altmissileFuncName bryar_alt_func -ammotype 2 -ammolowcount 15 -energypershot 2 -firetime 400 -range 8192 -altenergypershot 2 -altfiretime 400 -altrange 8192 -muzzleEffect bryar/muzzle_flash -} - -// WP_TURRET -{ -weapontype WP_TURRET -weaponclass weapon_turret -weaponmodel models/weapons2/noweap/noweap.md3 -weaponIcon icons/w_icon_turret -altenergypershot 1 -altrange 8192 -missileFuncName turret_func -ammotype 6 -ammolowcount 15 -energypershot 1 -firetime 400 -altfiretime 400 -range 8192 -muzzleEffect turret/muzzle_flash -} - -// AMMO_NONE -{ -AMMOTYPE AMMO_NONE -} - -// AMMO_FORCE -{ -AMMO AMMO_FORCE -AMMOMAX 100 -} - -// AMMO_BLASTER -{ -AMMO AMMO_BLASTER -AMMOMAX 300 -} - -// AMMO_POWERCELL -{ -AMMO AMMO_POWERCELL -AMMOMAX 300 -} - -// AMMO_METAL_BOLTS -{ -AMMO AMMO_METAL_BOLTS -AMMOMAX 400 -} - -// AMMO_ROCKETS -{ -AMMO AMMO_ROCKETS -AMMOMAX 10 -} - -// AMMO_EMPLACED -{ -AMMO AMMO_EMPLACED -AMMOMAX 999 -} - -// AMMO_THERMAL -{ -AMMO AMMO_THERMAL -AMMOMAX 10 -} - -// AMMO_TRIPMINE -{ -AMMO AMMO_TRIPMINE -AMMOMAX 5 -} - -// AMMO_DETPACK -{ -AMMO AMMO_DETPACK -AMMOMAX 5 -} \ No newline at end of file diff --git a/code/base/jk2config.cfg b/code/base/jk2config.cfg deleted file mode 100644 index a3683231..00000000 --- a/code/base/jk2config.cfg +++ /dev/null @@ -1,311 +0,0 @@ -// generated by Star Wars Jedi Outcast, do not modify -unbindall -bind SHIFT "+speed" -bind CTRL "+movedown" -bind ALT "force_pull" -bind TAB "cg_thirdperson !" -bind ENTER "invuse" -bind KP_INS "vstr easycheatforrandomizerdebug" -bind KP_DOWNARROW "use_seeker" -bind KP_LEFTARROW "use_lightamp_goggles" -bind KP_5 "use_sentry" -bind F1 "save quik*" -bind F2 "load quik" -bind F3 "force_speed" -bind F4 "force_distract" -bind SPACE "+moveup" -bind ) "invnext" -bind - "weapon 0" -bind . "+moveright" -bind / "+mlook" -bind 0 "weapon 10" -bind 1 "weapon 1" -bind 2 "weapon 2" -bind 3 "weapon 3" -bind 4 "weapon 4" -bind 5 "weapon 5" -bind 6 "weapon 6" -bind 7 "weapon 7" -bind 8 "weapon 8" -bind 9 "weapon 9" -bind A "force_throw" -bind B "use_bacta" -bind C "+movedown" -bind D "+moveright" -bind E "+use" -bind F "+strafe" -bind G "zoom" -bind L "saberAttackCycle" -bind M "datapad" -bind N "use_seeker" -bind O "centerview" -bind P "cg_thirdperson !" -bind Q "+moveleft" -bind R "weapnext" -bind S "+back" -bind V "+strafe" -bind W "soundstop" -bind X "vid_restart" -bind Z "+forward" -bind [ "invprev" -bind \ "weapongrabbed" -bind ] "invnext" -bind ` "toggleconsole" -bind ~ "toggleconsole" -bind F5 "force_heal" -bind F6 "+force_grip" -bind F7 "+force_lightning" -bind MWHEELUP "weapprev" -bind MWHEELDOWN "weapnext" -bind MOUSE1 "+attack" -bind MOUSE2 "+altattack" -bind PGUP "+lookup" -bind F10 "uimenu ingameloadmenu" -bind F11 "uimenu ingamesavemenu" -bind END "centerview" -bind PGDN "+lookdown" -bind MOUSE3 "zoom" -bind MOUSE5 "+force_lightning" -bind DOWNARROW "+back" -bind LEFTARROW "+left" -bind RIGHTARROW "+right" -seta cg_enableRandomizer "0" -seta com_maxfps "125" -seta sp_language "1" -seta in_midi "0" -seta in_midiport "1" -seta in_midichannel "1" -seta in_mididevice "0" -seta in_mouse "-1" -seta in_mouse_raw "1" -seta in_joystick "0" -seta in_joyBallScale "0.02" -seta joy_threshold "0.15" -seta js_ffmult "3.0" -seta joy_xbutton "1" -seta joy_ybutton "0" -seta sv_speedrunModeIL "0" -seta sv_speedrunModeCheckpoint "0" -seta sv_speedrunModeCheckpointSave "0" -seta sv_timedCheckpointMinX "0" -seta sv_timedCheckpointMinY "0" -seta sv_timedCheckpointMinZ "0" -seta sv_timedCheckpointMaxX "0" -seta sv_timedCheckpointMaxY "0" -seta sv_timedCheckpointMaxZ "0" -seta conAlpha "1.6" -seta panoNumShots "10" -seta cl_yawspeed "140" -seta cl_pitchspeed "140" -seta cl_anglespeedkey "1.5" -seta cl_maxpackets "30" -seta cl_packetdup "1" -seta cl_run "1" -seta sensitivity "5" -seta cl_mouseAccel "0" -seta cl_freelook "1" -seta cl_ingameVideo "1" -seta cl_VideoQuality "0" -seta cg_autoswitch "0" -seta m_pitch "0.022" -seta m_yaw "0.022" -seta m_forward "0.25" -seta m_side "0.25" -seta m_filter "0" -seta name "Kyle" -seta snaps "20" -seta sex "male" -seta handicap "100" -seta r_allowExtensions "1" -seta r_ext_compress_textures "1" -seta r_ext_compress_lightmaps "0" -seta r_ext_preferred_tc_method "0" -seta r_ext_gamma_control "1" -seta r_ext_multitexture "1" -seta r_ext_compiled_vertex_array "1" -seta r_ext_texture_env_add "1" -seta r_ext_texture_filter_anisotropic "1" -seta r_picmip "1" -seta r_detailtextures "1" -seta r_texturebits "0" -seta r_texturebitslm "0" -seta r_colorbits "32" -seta r_stereo "0" -seta r_stencilbits "8" -seta r_depthbits "24" -seta r_overBrightBits "1" -seta r_ignorehwgamma "0" -seta r_mode "8" -seta r_fullscreen "0" -seta r_customwidth "1600" -seta r_customheight "1024" -seta r_customaspect "1" -seta r_simpleMipMaps "1" -seta r_vertexLight "0" -seta r_subdivisions "4" -seta r_ignoreFastPath "1" -seta r_intensity "1" -seta r_lodCurveError "250" -seta r_lodbias "0" -seta r_flares "1" -seta r_lodscale "10" -seta r_ignoreGLErrors "1" -seta r_fastsky "0" -seta r_drawSun "0" -seta r_dynamiclight "1" -seta r_dlightBacks "1" -seta r_finish "0" -seta r_textureMode "GL_LINEAR_MIPMAP_LINEAR" -seta r_swapInterval "0" -seta r_gamma "1.359375" -seta r_facePlaneCull "1" -seta r_primitives "0" -seta r_showtriscolor "0" -seta cg_shadows "0" -seta r_modelpoolmegs "20" -seta r_lastValidRenderer "NVIDIA GeForce RTX 3060/PCIe/SSE2" -seta vid_xpos "10" -seta vid_ypos "2" -seta s_volume "0.039062" -seta s_volumeVoice "0.039062" -seta s_musicvolume "0.015625" -seta s_separation "0.5" -seta s_khz "22" -seta s_allowDynamicMusic "1" -seta s_mixahead "0.2" -seta s_mixPreStep "0.05" -seta s_language "francais" -seta s_mp3overhead "31756" -seta s_UseOpenAL "0" -seta s_soundpoolmegs "25" -seta use_ff "1" -seta ff_channels "0,0;1,0;2,0;3,0;4,0;5,0" -seta ff_delay "40" -seta cg_drawCrosshair "1" -seta cg_marks "1" -seta ui_menuFiles "ui/menus.txt" -seta ui_smallFont "0.25" -seta ui_bigFont "0.4" -seta cg_hudFiles "ui/jk2hud.txt" -seta ui_r_glCustom "4" -seta g_subtitles "2" -seta cg_saberAutoThird "0" -seta cg_gunAutoFirst "1" -seta cg_drawSpeed "1" -seta g_spskill "0" -seta cg_crosshairForceHint "1" -seta cm_playerCurveClip "1" -seta cg_drawGun "1" -seta cg_stereoSeparation "0.4" -seta cg_draw2D "1" -seta cg_drawStatus "1" -seta cg_drawTimer "1" -seta cg_drawFPS "1" -seta cg_drawServerFPS "1" -seta cg_drawSnapshot "0" -seta cg_drawAmmoWarning "1" -seta cg_dynamicCrosshair "1" -seta cg_crosshairIdentifyTarget "1" -seta cg_crosshairSize "24" -seta cg_crosshairX "0" -seta cg_crosshairY "0" -seta cg_simpleItems "0" -seta cg_runpitch "0.002" -seta cg_runroll "0.005" -seta cg_bobup "0.005" -seta cg_bobpitch "0.002" -seta cg_bobroll "0.002" -seta cg_missionInfoCentered "1" -seta cg_reliableAnimSounds "1" -seta cg_drawSecrets "0" -seta cg_drawSpeedrunTotalTimer "4" -seta cg_drawSpeedrunLevelTimer "1" -seta cg_drawOverbounceInfo "0" -seta cg_drawJumpHelper "0" -seta cg_jumpHelperX "0" -seta cg_jumpHelperY "0" -seta cg_jumpHelperWidth "300" -seta cg_jumpHelperHeight "20" -seta cg_jumpHelperHorizontal "1" -seta cg_jumpHelperMirror "1" -seta cg_jumpHelperAutoScale "0" -seta cg_jumpHelperCrouch "1" -seta cg_jumpHelperCurrentScale "0.5" -seta cg_jumpHelperColorBackgroundR "0.0" -seta cg_jumpHelperColorBackgroundG "0.0" -seta cg_jumpHelperColorBackgroundB "0.0" -seta cg_jumpHelperColorBackgroundA "0.2" -seta cg_jumpHelperColorCancelR "0.8" -seta cg_jumpHelperColorCancelG "0.8" -seta cg_jumpHelperColorCancelB "0.8" -seta cg_jumpHelperColorCancelA "0.75" -seta cg_jumpHelperColorCrouchR "0.0" -seta cg_jumpHelperColorCrouchG "1.0" -seta cg_jumpHelperColorCrouchB "1.0" -seta cg_jumpHelperColorCrouchA "0.75" -seta cg_jumpHelperColorCrouchExtendR "0.0" -seta cg_jumpHelperColorCrouchExtendG "0.333" -seta cg_jumpHelperColorCrouchExtendB "0.333" -seta cg_jumpHelperColorCrouchExtendA "0.375" -seta cg_jumpHelperColorCurrentR "1.0" -seta cg_jumpHelperColorCurrentG "1.0" -seta cg_jumpHelperColorCurrentB "1.0" -seta cg_jumpHelperColorCurrentA "0.75" -seta cg_jumpHelperColorExtendR "0.0" -seta cg_jumpHelperColorExtendG "0.5" -seta cg_jumpHelperColorExtendB "0.125" -seta cg_jumpHelperColorExtendA "0.375" -seta cg_jumpHelperColorOptimalR "0.0" -seta cg_jumpHelperColorOptimalG "1.0" -seta cg_jumpHelperColorOptimalB "0.25" -seta cg_jumpHelperColorOptimalA "0.75" -seta cg_speedScale "0.9" -seta cg_speedX "0" -seta cg_speedY "75" -seta cg_speedColorR "1.0" -seta cg_speedColorG "1.0" -seta cg_speedColorB "1.0" -seta cg_speedColorA "0.1" -seta cg_drawStrafeHelper "0" -seta cg_strafeHelperCenter "1" -seta cg_strafeHelperCenterMarker "1" -seta cg_strafeHelperHeight "20" -seta cg_strafeHelperScale "4" -seta cg_strafeHelperSpeedScale "0.9" -seta cg_strafeHelperSpeedX "0" -seta cg_strafeHelperSpeedY "0" -seta cg_strafeHelperY "50" -seta cg_strafeHelperColorAcceleratingR "0.0" -seta cg_strafeHelperColorAcceleratingG "0.5" -seta cg_strafeHelperColorAcceleratingB "0.125" -seta cg_strafeHelperColorAcceleratingA "0.375" -seta cg_strafeHelperColorOptimalR "0.0" -seta cg_strafeHelperColorOptimalG "1.0" -seta cg_strafeHelperColorOptimalB "0.25" -seta cg_strafeHelperColorOptimalA "0.75" -seta cg_strafeHelperColorCenterMarkerR "1.0" -seta cg_strafeHelperColorCenterMarkerG "1.0" -seta cg_strafeHelperColorCenterMarkerB "1.0" -seta cg_strafeHelperColorCenterMarkerA "0.75" -seta cg_strafeHelperColorSpeedR "1.0" -seta cg_strafeHelperColorSpeedG "1.0" -seta cg_strafeHelperColorSpeedB "1.0" -seta cg_strafeHelperColorSpeedA "0.9" -seta g_dismemberment "3" -seta g_dismemberProbabilities "1" -seta g_saberAutoBlocking "1" -seta g_saberRealisticCombat "0" -seta g_saberMoveSpeed "1" -seta g_saberAnimSpeed "1" -seta g_saberAutoAim "1" -seta g_saber_color "yellow" -seta g_speedFactorLanding "1.0" -seta ui_iscensored "0" -seta d_slowmodeath "0" -seta easycheatforrandomizerdebug "helpusobi 1 ; god ; give all ; setforceall 3" -seta svfps1 "sv_fps 20; echo sv_fps 20; bind kp_ins vstr svfps2" -seta svfps2 "sv_fps 125;echo sv_fps 125; bind kp_ins vstr svfps1" -seta r_weatherScale "1" -seta cg_drawSeed "1" -seta cg_useSetSeed "0" -seta cg_setSeed "1098786026" From 6301fe007a62b4b4243793784e9c8f0def346ad9 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sat, 9 Nov 2024 18:39:20 +0000 Subject: [PATCH 30/62] cleanup and ignore commit 2 --- .gitignore | 4 ++-- code/cgame/cg_draw.cpp | 10 +--------- code/game/NPC_spawn.cpp | 6 +----- code/game/bg_misc.cpp | 13 ++----------- code/game/g_client.cpp | 3 --- code/game/g_cmds.cpp | 8 +------- code/game/g_misc_model.cpp | 11 ----------- code/game/q_shared.h | 5 ----- code/speedrun/speedrun_timer_includes.cpp | 17 ----------------- code/ui/ui_main.cpp | 3 +-- 10 files changed, 8 insertions(+), 72 deletions(-) diff --git a/.gitignore b/.gitignore index 94a675de..9e5d16e2 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,5 @@ **/SHDebug *vcxproj.user *.tlog -code/base/maps/* -code/base/saves/* \ No newline at end of file +code/base/* +code/demo/* \ No newline at end of file diff --git a/code/cgame/cg_draw.cpp b/code/cgame/cg_draw.cpp index 27c4a91b..f216dfe4 100644 --- a/code/cgame/cg_draw.cpp +++ b/code/cgame/cg_draw.cpp @@ -2715,15 +2715,7 @@ static void CG_Draw2D( void ) CG_DrawOverbounceInfo(); } - // Encapsulate every code related to the Randomizer behind this kind of condition. - /*if (cg_enableRandomizer.integer) - { - if (cg_drawSeed.integer) - { - CG_DrawSeed(y); - } - }*/ - if (cg_drawSeed.integer) + if (cg_enableRandomizer.integer && cg_drawSeed.integer) { CG_DrawSeed(y); } diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 1673786d..8f64e2d7 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -2802,16 +2802,12 @@ char lastKnownMap[32] = "first_iteration"; void MapChanged() { - //strcpy(lastKnownMap, level.mapname); - //lastKnownMap = level.mapname; + //Reset NPCs when changing maps for (int i = 0; i < tabSize; i++) { tabLockedInNPC[i] = -1; } currentTabPosition = 0; - // We might have to lock Kyle, we will see what happen. - // tabLockedInNPC[0] = 0; - // currentTabPosition = 1; } void CheckIfMapChanged() diff --git a/code/game/bg_misc.cpp b/code/game/bg_misc.cpp index f919a8b4..7af28575 100644 --- a/code/game/bg_misc.cpp +++ b/code/game/bg_misc.cpp @@ -183,14 +183,12 @@ FindItemForWeapon =============== */ gitem_t *FindItemForWeapon( weapon_t weapon ) { - // Posto : this is called during map load, to know what kind of weapon is on the ground (ex : cairn_dock1). It's in this .cpp that I have to randomize things ?????!!!!! + // Posto : this is called during map load, to know what kind of weapon is on the ground (ex : cairn_dock1). int i; for ( i = 1 ; i < bg_numItems ; i++ ) { if ( bg_itemlist[i].giType == IT_WEAPON && bg_itemlist[i].giTag == weapon ) { - //int rng = rand() % 5 + 2; - //return &bg_itemlist[rng]; return &bg_itemlist[i]; } } @@ -203,15 +201,12 @@ gitem_t *FindItemForWeapon( weapon_t weapon ) { gitem_t *FindItemForInventory( int inv ) { // Posto : when called in kejim_post, only bacta and binocular is returned; while on cairndock_1, a lot of things is returned (sentry, seeker). - // It MUST be here that I randomize things, but how ? int i; gitem_t *it; // Now just check for any other kind of item. for ( i = 1 ; i < bg_numItems ; i++ ) { - //int rng = i + rand() % 2; - //it = &bg_itemlist[rng]; it = &bg_itemlist[i]; if ( it->giType == IT_HOLDABLE ) @@ -241,8 +236,6 @@ gitem_t *FindItemForAmmo( ammo_t ammo ) { if ( bg_itemlist[i].giType == IT_AMMO && bg_itemlist[i].giTag == ammo ) { - //int rng = rand() % 4 + 1; - //return &bg_itemlist[rng]; return &bg_itemlist[i]; } } @@ -261,10 +254,8 @@ gitem_t *FindItem( const char *className ) { int i; for ( i = 1 ; i < bg_numItems ; i++ ) { - if (!Q_stricmp(bg_itemlist[i].classname, className)) + if ( !Q_stricmp( bg_itemlist[i].classname, className ) ) { - //int rng = rand() % 4 + 1; - //return &bg_itemlist[rng]; return &bg_itemlist[i]; } } diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index 208fda63..d9028d8c 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -1523,10 +1523,8 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded else { G_LoadAnimFileSet( ent, "kyle" ); - //G_LoadAnimFileSet(ent, "jan"); // Posto : maybe it's here that we can 'randomize' how we look like ? Not being Kyle could be funny G_SetSkin( ent, "kyle", NULL ); - //G_SetSkin(ent, "jan", NULL); } } else @@ -1696,7 +1694,6 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded ent->weaponModel = -1; // Posto : maybe it's here that we can 'randomize' how we look like ? Not being Kyle could be funny G_SetG2PlayerModel( ent, "kyle", NULL, NULL, NULL ); - //G_SetG2PlayerModel(ent, "jan", NULL, NULL, NULL); } else { diff --git a/code/game/g_cmds.cpp b/code/game/g_cmds.cpp index c50be688..8775aa47 100644 --- a/code/game/g_cmds.cpp +++ b/code/game/g_cmds.cpp @@ -6,9 +6,6 @@ #include "objectives.h" #include "wp_saber.h" -//#include <..\game\NPC_spawn.cpp> -//extern void RandomizerDebugCommandCatcher(int page); // It's declared in NPC_spawn.cpp - extern bool in_camera; extern void ForceThrow( gentity_t *self, qboolean pull ); @@ -1036,10 +1033,7 @@ void ClientCommand( int clientNum ) { // Posto : maybe adding a command is here ? No, this is called later if (Q_stricmp(cmd, "give") == 0) Cmd_Give_f(ent); - /* - else if (Q_stricmp(cmd, "randomizer_debug") == 0) - RandomizerDebugCommandCatcher(); - */ + else if (Q_stricmp (cmd, "god") == 0) Cmd_God_f (ent); else if (Q_stricmp (cmd, "undying") == 0) diff --git a/code/game/g_misc_model.cpp b/code/game/g_misc_model.cpp index c9ea4f3d..661fb35a 100644 --- a/code/game/g_misc_model.cpp +++ b/code/game/g_misc_model.cpp @@ -419,11 +419,6 @@ void SP_misc_model_gun_rack( gentity_t *ent ) { for ( int i = 0; i < ct; i++ ) { - // Posto : I might be hated for this, but randomizing weapons here should be the best - if (cg_enableRandomizer.integer) - { - //itemList[i] = FindItemForWeapon((weapon_t)GetRandomizedWeapon()); - } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 2, ( i - 1 ) * 9 + crandom() * 2, ofz[i] ); } } @@ -514,7 +509,6 @@ void SP_misc_model_ammo_rack( gentity_t *ent ) gi.linkentity( ent ); } -// Posto : let me edit a bit, just to test // AMMO RACK!! void spawn_rack_goods( gentity_t *ent ) { @@ -600,11 +594,6 @@ void spawn_rack_goods( gentity_t *ent ) { for ( int i = 0; i < ct; i++ ) { - // Posto : I might be hated for this, but randomizing ammos here should be the best - if (cg_enableRandomizer.integer) - { - //itemList[i] = FindItemForAmmo((ammo_t)GetRandomizedAmmo()); - } GunRackAddItem( itemList[i], ent->s.origin, ent->s.angles, crandom() * 0.5f, (i-1)* 8, 7.0f ); } } diff --git a/code/game/q_shared.h b/code/game/q_shared.h index dd077c79..dd5f3b40 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1156,7 +1156,6 @@ typedef struct { #define MAX_LOCATIONS 64 #define GENTITYNUM_BITS 10 // don't need to send any more -//#define GENTITYNUM_BITS 11 // Posto : ok never touch this, or the game explode #define MAX_GENTITIES (1< MAX_CONFIGSTRINGS #endif -//#define MAX_GAMESTATE_CHARS 16000 #define MAX_GAMESTATE_CHARS 32000 // Posto : might need to increase that typedef struct { int stringOffsets[MAX_CONFIGSTRINGS]; diff --git a/code/speedrun/speedrun_timer_includes.cpp b/code/speedrun/speedrun_timer_includes.cpp index 035b2b98..e34ae22c 100644 --- a/code/speedrun/speedrun_timer_includes.cpp +++ b/code/speedrun/speedrun_timer_includes.cpp @@ -1,13 +1,6 @@ #include "speedrun_timer_includes.h" #include "../../server/exe_headers.h" -/* -// Randomizer -//#include "../cgame/cg_main.cpp" -extern vmCvar_t cg_enableRandomizer; -extern vmCvar_t cg_useSetSeed; -extern vmCvar_t cg_setSeed; -*/ namespace { @@ -22,16 +15,6 @@ void SpeedrunTimerPrint(const char* levelTimeString, totalTimeString); } Com_Printf(S_COLOR_RED "=========================\n"); - // Randomizer - /* - if (cg_enableRandomizer.integer) - { - Com_Printf(S_COLOR_RED "=========================\n"); - Com_Printf(S_COLOR_GREEN "Randomizer Seed: " S_COLOR_WHITE "%s\n", cg_setSeed); - Com_Printf(S_COLOR_RED "=========================\n"); - } - */ - } void SpeedrunTimerPrintNoNotify(const char* levelTimeString, diff --git a/code/ui/ui_main.cpp b/code/ui/ui_main.cpp index 409a1d0c..a74838a8 100644 --- a/code/ui/ui_main.cpp +++ b/code/ui/ui_main.cpp @@ -618,8 +618,7 @@ extern void FS_Restart( void ); } else if (Q_stricmp(name, "startgame") == 0) { - Menus_CloseAll(); - + Menus_CloseAll(); if ( Cvar_VariableIntegerValue("com_demo") ) { #ifdef FINAL_BUILD From 6e665e17ed2987f9dec9196b35e788b50cef27fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Sat, 9 Nov 2024 21:14:31 +0100 Subject: [PATCH 31/62] Added the old values on q_shared.h in commented code. Also added a small check so that the force power can't go past 3. --- code/game/g_items.cpp | 5 +++-- code/game/q_shared.h | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index c7825e42..5a195cc9 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -381,6 +381,7 @@ int Pickup_Holocron( gentity_t *ent, gentity_t *other ) int forceLevel = ent->count; //Always increment if (cg_enableRandomizer.integer) { + if (other->client->ps.forcePowerLevel[forcePower] < 3) forceLevel = other->client->ps.forcePowerLevel[forcePower] + 1; } // check if out of range @@ -818,7 +819,7 @@ void FinishSpawningItem( gentity_t *ent ) { // For tests purpose only int rng = rand() % 54; itemNew = bg_itemlist + rng; - // No saber, no baton, no strange items. + // No baton, no strange items. if ((strcmp(level.mapname, "yavin_trial"))) { while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 0) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) @@ -840,7 +841,7 @@ void FinishSpawningItem( gentity_t *ent ) { ent->classname == item->classname; ent->item = item; } - else // Don't do anything if we are in trial (or other exceptions), we CAN'T not get force power + else // Don't do anything if we are in trial (or other exceptions), we CAN'T not get these force powers { } diff --git a/code/game/q_shared.h b/code/game/q_shared.h index dd5f3b40..3b955ceb 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1166,6 +1166,8 @@ typedef struct { #define ENTITYNUM_MAX_NORMAL (MAX_GENTITIES-2) +//#define MAX_MODELS 256 // Old values +//#define MAX_SOUNDS 256 // Old values #define MAX_MODELS 512 // Posto : For the Randomizer, we might need to increase it. #define MAX_SOUNDS 512 // Same for that @@ -1185,6 +1187,7 @@ Ghoul2 Insert Start Ghoul2 Insert End */ +// #define MAX_CONFIGSTRINGS 1024 // Old values #define MAX_CONFIGSTRINGS 2048 // Posto : we might need to double this, I understand if we have performance issue // these are the only configstrings that the system reserves, all the @@ -1229,6 +1232,7 @@ Ghoul2 Insert End #error overflow: (CS_MAX) > MAX_CONFIGSTRINGS #endif +// #define MAX_GAMESTATE_CHARS 16000 // Old value #define MAX_GAMESTATE_CHARS 32000 // Posto : might need to increase that typedef struct { int stringOffsets[MAX_CONFIGSTRINGS]; From 2ce615c5ddd4b8b81e2abea755489b6acb3b484b Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sun, 10 Nov 2024 19:35:27 +0000 Subject: [PATCH 32/62] reset when loading auto_kejim_post --- code/game/g_main.cpp | 2 +- code/game/g_public.h | 1 + code/server/sv_savegame.cpp | 11 ++++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index b9126b0c..c224e7d6 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -595,7 +595,7 @@ void InitGame( const char *mapname, const char *spawntarget, int checkSum, cons if (cg_enableRandomizer.integer) { - if (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) { + if ( (!Q_stricmp(mapname, "kejim_post") && eSavedGameJustLoaded == eNO) || eSavedGameJustLoaded == eRESET) { RandomizerUtils::RegenerateSeed(); } char seed[MAX_STRING_CHARS]; diff --git a/code/game/g_public.h b/code/game/g_public.h index 90c92b5e..44f67a53 100644 --- a/code/game/g_public.h +++ b/code/game/g_public.h @@ -51,6 +51,7 @@ typedef enum eNO = 0, eFULL, eAUTO, + eRESET //Used when loading auto_kejim_post to reset } SavedGameJustLoaded_e; diff --git a/code/server/sv_savegame.cpp b/code/server/sv_savegame.cpp index 793607eb..e843c9b0 100644 --- a/code/server/sv_savegame.cpp +++ b/code/server/sv_savegame.cpp @@ -1034,7 +1034,16 @@ qboolean SG_ReadSavegame(const char *psPathlessBaseName) // read game state qbAutosave = ReadGame(); - eSavedGameJustLoaded = (qbAutosave)?eAUTO:eFULL; + + //When resetting using the auto_kejim_post save + if (Cvar_VariableIntegerValue("cg_enableRandomizer") && !strcmp("auto_kejim_post", psPathlessBaseName) ) + { + eSavedGameJustLoaded = eRESET; + } + else { + eSavedGameJustLoaded = (qbAutosave) ? eAUTO : eFULL; + } + SV_SpawnServer(sMapCmd, eForceReload_NOTHING, (eSavedGameJustLoaded != eFULL) ); // note that this also trashes the whole G_Alloc pool as well (of course) From d0592afaed7a7972c2a4b63222648f089eac1def Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 11 Nov 2024 18:37:19 +0000 Subject: [PATCH 33/62] Quadruple entity limit, double FX limit --- code/game/q_shared.h | 4 ++-- code/renderer/tr_local.h | 4 ++-- code/renderer/tr_main.cpp | 2 +- code/renderer/tr_types.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/q_shared.h b/code/game/q_shared.h index 3b955ceb..ce7a7f77 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1155,7 +1155,7 @@ typedef struct { #define MAX_CLIENTS 1 // 128 // absolute limit #define MAX_LOCATIONS 64 -#define GENTITYNUM_BITS 10 // don't need to send any more +#define GENTITYNUM_BITS 12 // don't need to send any more #define MAX_GENTITIES (1<> QSORT_FOGNUM_SHIFT ) & 31; *shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ]; - *entityNum = ( sort >> QSORT_ENTITYNUM_SHIFT ) & 1023; + *entityNum = (sort >> QSORT_ENTITYNUM_SHIFT) & (MAX_GENTITIES - 1); //Higher entity limit *dlightMap = sort & 3; } diff --git a/code/renderer/tr_types.h b/code/renderer/tr_types.h index 6d4f4ccb..72578d73 100644 --- a/code/renderer/tr_types.h +++ b/code/renderer/tr_types.h @@ -4,7 +4,7 @@ #include "..\game\ghoul2_shared.h" #define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces -#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing +#define MAX_ENTITIES (MAX_GENTITIES - 1) // can't be increased without changing drawsurf bit packing //Raise ent limit // renderfx flags #define RF_MORELIGHT 0x00001 // allways have some light (viewmodel, some items) From 546ac8f4cc1dfd9819f5d3226274c68b6d706d62 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 11 Nov 2024 20:50:15 +0000 Subject: [PATCH 34/62] Respect set seed value --- code/randomizer/RandomizerUtils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp index e7a60541..067adc99 100644 --- a/code/randomizer/RandomizerUtils.cpp +++ b/code/randomizer/RandomizerUtils.cpp @@ -43,7 +43,7 @@ void RandomizerUtils::seedRandomizer(std::string seedString, std::string levelNa void RandomizerUtils::RegenerateSeed() { //Reinitialise randomizer seed value if we're not using setSeed - if (cg_enableRandomizer.integer) + if (cg_enableRandomizer.integer && !cg_useSetSeed.integer) { //Get System Epoch Time auto duration = system_clock::now().time_since_epoch(); From 5ac8ceeda310960a4b486c2f3e8aa1f71b9a1a8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Tue, 12 Nov 2024 19:24:10 +0100 Subject: [PATCH 35/62] Added old values of edited variable important for the engine. Also added Tavion and Desann to the spawn pool. Also patched the Stromtroopers on artus_topside. --- code/game/NPC_spawn.cpp | 33 +++++++++++++++++++++++++-------- code/game/g_items.cpp | 3 +++ code/game/q_shared.h | 2 ++ code/renderer/tr_local.h | 1 + code/renderer/tr_main.cpp | 1 + code/renderer/tr_types.h | 1 + 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 8f64e2d7..37b6cb7f 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -3005,10 +3005,10 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_MonMothma(self); PopulateNPCTab(rng); break; - case 5: // Desann and Tavion are too hard to handle, I will keep them out for now - //SP_NPC_Tavion(self); - //PopulateNPCTab(rng); - SP_NPC_Spawn_Random(self); + case 5: // Desann and Tavion are too hard to handle, buuuut we have force in earlt levels now + SP_NPC_Tavion(self); + PopulateNPCTab(rng); + //SP_NPC_Spawn_Random(self); break; case 6: // Il a une IA au moins ? SP_NPC_Reelo(self); @@ -3018,10 +3018,10 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_Galak(self); PopulateNPCTab(rng); break; - case 8: // Desann and Tavion are too hard to handle, I will keep them out for now - //SP_NPC_Desann(self); - //PopulateNPCTab(rng); - SP_NPC_Spawn_Random(self); + case 8: // Desann and Tavion are too hard to handle, buuuut we have force in earlt levels now + SP_NPC_Desann(self); + PopulateNPCTab(rng); + //SP_NPC_Spawn_Random(self); break; case 9: // Il a une IA au moins ? SP_NPC_Bartender(self); @@ -3409,6 +3409,23 @@ void SP_NPC_Stormtrooper_Random(gentity_t* self) SP_NPC_Stormtrooper(self); return; } + if (strcmp(lastKnownMap, "artus_topside") == 0) + { + if (self->behaviorSet[0]) // Check for NULL + { + if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners") == 0) + { + SP_NPC_Stormtrooper(self); + return; + } + if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners_crouch") == 0) + { + SP_NPC_Stormtrooper(self); + return; + } + } + + } SP_NPC_Spawn_Random(self); } else SP_NPC_Stormtrooper(self); diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 5a195cc9..13e63e21 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -829,12 +829,15 @@ void FinishSpawningItem( gentity_t *ent ) { } if (itemNew->giType == IT_HOLOCRON) { + // Maybe do one last roll because the game is giving us many force. Maybe 50/50 ? ent->count = 0; + updateItemMinsMaxs(itemNew); } else { //Expand 'hitbox' of randomly spawned items a little so they can be picked up while partially clipped into geometry //not for holocrons as their pickup range is pretty large already + // Posto Edit : I encountered holocron that were inside walls, so might as well update their hitbox too updateItemMinsMaxs(itemNew); } item = itemNew; diff --git a/code/game/q_shared.h b/code/game/q_shared.h index ce7a7f77..71d7cb4c 100644 --- a/code/game/q_shared.h +++ b/code/game/q_shared.h @@ -1155,6 +1155,7 @@ typedef struct { #define MAX_CLIENTS 1 // 128 // absolute limit #define MAX_LOCATIONS 64 +//#define #define GENTITYNUM_BITS 10 // Old value #define GENTITYNUM_BITS 12 // don't need to send any more #define MAX_GENTITIES (1<> QSORT_FOGNUM_SHIFT ) & 31; *shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & (MAX_SHADERS-1) ]; + //*entityNum = (sort >> QSORT_ENTITYNUM_SHIFT) & 1023); *entityNum = (sort >> QSORT_ENTITYNUM_SHIFT) & (MAX_GENTITIES - 1); //Higher entity limit *dlightMap = sort & 3; } diff --git a/code/renderer/tr_types.h b/code/renderer/tr_types.h index 72578d73..cd89acc0 100644 --- a/code/renderer/tr_types.h +++ b/code/renderer/tr_types.h @@ -4,6 +4,7 @@ #include "..\game\ghoul2_shared.h" #define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces +//#define MAX_ENTITIES 1023 // Old value #define MAX_ENTITIES (MAX_GENTITIES - 1) // can't be increased without changing drawsurf bit packing //Raise ent limit // renderfx flags From b6b6015fb9d4aa0bb1e6b77984ee40549e276d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Wed, 13 Nov 2024 13:31:04 +0100 Subject: [PATCH 36/62] Fixed the behavior of the lightsaber before yavin_trial + added a random saber style at pickup. --- code/game/g_items.cpp | 32 ++++++++++++++++++++++++++++++++ code/game/wp_saber.cpp | 9 ++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 5a195cc9..9a69b419 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -267,6 +267,38 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) if ( ent->item->giTag == WP_SABER && !hadWeapon ) { WP_SaberInitBladeData( other ); + if (cg_enableRandomizer.integer) // In case we get a saber before trial, get defense 1 and offense 1 so that the saber won't have bugged behavior. + { + if ((strcmp(level.mapname,"yavin_trial") != 0 )) + { + // We are getting a saber before trial, but by doing that we lock on medium style + // The only way to bypass this is to act like get_saber script : actually getting the saber THEN giving the force power + other->client->ps.forcePowerLevel[FP_SABER_OFFENSE] = 1; + other->client->ps.forcePowerLevel[FP_SABER_DEFENSE] = 1; + + other->client->ps.forcePowersKnown |= (1 << FP_SABER_OFFENSE); + other->client->ps.forcePowersKnown |= (1 << FP_SABER_DEFENSE); + + missionInfo_Updated = qtrue; // Activate flashing text + + gi.cvar_set("cg_updatedDataPadForcePower1", va("%d", FP_SABER_OFFENSE + 1)); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower1.integer = FP_SABER_OFFENSE + 1; + gi.cvar_set("cg_updatedDataPadForcePower2", "0"); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower2.integer = 0; + gi.cvar_set("cg_updatedDataPadForcePower3", "0"); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower3.integer = 0; + + gi.cvar_set("cg_updatedDataPadForcePower1", va("%d", FP_SABER_DEFENSE + 1)); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower1.integer = FP_SABER_DEFENSE + 1; + gi.cvar_set("cg_updatedDataPadForcePower2", "0"); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower2.integer = 0; + gi.cvar_set("cg_updatedDataPadForcePower3", "0"); // The +1 is offset in the print routine. + cg_updatedDataPadForcePower3.integer = 0; + + + + } + } } if ( other->s.number ) diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 895a9bcf..e8ae7dba 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -438,7 +438,14 @@ void WP_SaberInitBladeData( gentity_t *ent ) { if ( !ent->client->ps.saberAnimLevel ) {//initialize, but don't reset - ent->client->ps.saberAnimLevel = FORCE_LEVEL_2; + if (cg_enableRandomizer.integer) // Random saber style at pickup. + { + ent->client->ps.saberAnimLevel = rand() % 3 + 1; + } + else + { + ent->client->ps.saberAnimLevel = FORCE_LEVEL_2; + } } cg.saberAnimLevelPending = ent->client->ps.saberAnimLevel; if ( ent->client->sess.missionStats.weaponUsed[WP_SABER] <= 0 ) From 5f855b53b7b4d2ddc6dc866c20a0a571a0b66614 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 21 Nov 2024 17:58:53 +0100 Subject: [PATCH 37/62] Added a second roll when rolling for a saber and force powers. --- code/game/g_items.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 9a69b419..6e987fb2 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -848,20 +848,29 @@ void FinishSpawningItem( gentity_t *ent ) { if (cg_enableRandomizer.integer) { itemOld = item; - // For tests purpose only - int rng = rand() % 54; + int rng = rand() % 53 + 1; itemNew = bg_itemlist + rng; // No baton, no strange items. if ((strcmp(level.mapname, "yavin_trial"))) { + // No strange weapon, 'shield' and 'datapad' while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 0) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) { rng = rand() % 53 + 1; itemNew = bg_itemlist + rng; } - if (itemNew->giType == IT_HOLOCRON) + if (itemNew->giType == IT_HOLOCRON || itemNew->giTag == WP_SABER) // In case we roll a saber or an holocron, we shall roll a 33/66 to keep the item or not { - ent->count = 0; + rng = rand() % 3; + if (!rng) // We rolled a 0, reroll once + { + rng = rand() % 53 + 1; + itemNew = bg_itemlist + rng; + } + // else, we rolled a >=1, we keep the saber/holocron + + if (itemNew->giType == IT_HOLOCRON) ent->count = 0; + updateItemMinsMaxs(itemNew); } else { From 58c4fa08a08fc0c564940dd68ea410daf266527a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Fri, 6 Dec 2024 14:35:18 +0100 Subject: [PATCH 38/62] Get random saber style based on game time --- code/game/g_items.cpp | 11 ++++++++--- code/game/wp_saber.cpp | 7 ++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 6e987fb2..62061719 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -854,18 +854,23 @@ void FinishSpawningItem( gentity_t *ent ) { if ((strcmp(level.mapname, "yavin_trial"))) { // No strange weapon, 'shield' and 'datapad' - while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag <= 0) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) + while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) { rng = rand() % 53 + 1; itemNew = bg_itemlist + rng; } - if (itemNew->giType == IT_HOLOCRON || itemNew->giTag == WP_SABER) // In case we roll a saber or an holocron, we shall roll a 33/66 to keep the item or not + if (itemNew->giType == IT_HOLOCRON || (itemNew->giTag == WP_SABER && itemNew->giType == IT_WEAPON)) // In case we roll a saber or an holocron, we shall roll a 33/66 to keep the item or not { rng = rand() % 3; if (!rng) // We rolled a 0, reroll once { rng = rand() % 53 + 1; - itemNew = bg_itemlist + rng; + // No strange weapon, 'shield' and 'datapad' + while ((itemNew->giTag >= 13 && itemNew->giTag <= 22) || (itemNew->giTag == 43) || (itemNew->giTag == 45)) + { + rng = rand() % 53 + 1; + itemNew = bg_itemlist + rng; + } } // else, we rolled a >=1, we keep the saber/holocron diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index e8ae7dba..fb79ee4e 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -438,11 +438,12 @@ void WP_SaberInitBladeData( gentity_t *ent ) { if ( !ent->client->ps.saberAnimLevel ) {//initialize, but don't reset - if (cg_enableRandomizer.integer) // Random saber style at pickup. + if (cg_enableRandomizer.integer) // Random saber style at pickup, but I need to NOT call rand() to keep NPC spawn consistent. { - ent->client->ps.saberAnimLevel = rand() % 3 + 1; + ent->client->ps.saberAnimLevel = (level.framenum + level.time) % 3 + 1; + int i = 0; } - else + else // Normal gameplay (and yes, there is a glitch to get fast style in trial) { ent->client->ps.saberAnimLevel = FORCE_LEVEL_2; } From 52752170848f4f95f4ecab48c3198a6be85b922d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Sat, 7 Dec 2024 00:01:51 +0100 Subject: [PATCH 39/62] Base game fixes (#7) * Added a fix to get items inside artus_mine crates. * Adde comments about adding a variable about 'base game fixes' that are not about the randomizer * Added a variable to enable/disable base game fixes * Added a fix for un-pickage metal ammo on ns_starpad --- code/cgame/cg_local.h | 2 ++ code/cgame/cg_main.cpp | 6 +++++- code/game/g_breakable.cpp | 41 +++++++++++++++++++++++++++++++++++++++ code/game/g_items.cpp | 18 +++++++++++++++++ code/game/wp_saber.cpp | 2 +- 5 files changed, 67 insertions(+), 2 deletions(-) diff --git a/code/cgame/cg_local.h b/code/cgame/cg_local.h index 6d1e880e..fd8b8baa 100644 --- a/code/cgame/cg_local.h +++ b/code/cgame/cg_local.h @@ -697,6 +697,8 @@ extern vmCvar_t cg_strafeHelperColorSpeedA; extern vmCvar_t cg_enableRandomizer; extern vmCvar_t cg_drawSeed; extern vmCvar_t cg_setSeed; +//Additions for Base Game fixes (ex : artus_mine crates to get all pickups) +extern vmCvar_t cg_baseGameFixes; void CG_NewClientinfo( int clientNum ); // diff --git a/code/cgame/cg_main.cpp b/code/cgame/cg_main.cpp index aa7cb2bb..45026c3f 100644 --- a/code/cgame/cg_main.cpp +++ b/code/cgame/cg_main.cpp @@ -395,6 +395,8 @@ vmCvar_t cg_enableRandomizer; vmCvar_t cg_drawSeed; vmCvar_t cg_useSetSeed; vmCvar_t cg_setSeed; +// Additions for Base Game fixes (ex : artus_mine crates to get all pickups) +vmCvar_t cg_baseGameFixes; typedef struct { vmCvar_t *vmCvar; @@ -584,7 +586,9 @@ Ghoul2 Insert End { &cg_enableRandomizer, "cg_enableRandomizer", "0", CVAR_ARCHIVE }, // By default, it's disabled { &cg_drawSeed, "cg_drawSeed", "0", CVAR_ARCHIVE }, { &cg_useSetSeed, "cg_useSetSeed", "0", CVAR_ARCHIVE }, - { &cg_setSeed, "cg_setSeed", "", CVAR_ARCHIVE } + { &cg_setSeed, "cg_setSeed", "", CVAR_ARCHIVE }, + // Additions for BaseGame fixes + { &cg_baseGameFixes, "cg_baseGameFixes", "0", CVAR_ARCHIVE } }; int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); diff --git a/code/game/g_breakable.cpp b/code/game/g_breakable.cpp index 4494d9e6..586f58f7 100644 --- a/code/game/g_breakable.cpp +++ b/code/game/g_breakable.cpp @@ -864,6 +864,9 @@ set size better? multiple damage models? custom explosion effect/sound? */ +//Additions for Base Game fixes (ex : artus_mine crates to get all pickups) +extern vmCvar_t cg_baseGameFixes; + void SP_misc_model_breakable( gentity_t *ent ) { char damageModel[MAX_QPATH]; @@ -883,6 +886,44 @@ void SP_misc_model_breakable( gentity_t *ent ) damageModel[len] = 0; //chop extension strncpy( chunkModel, damageModel, sizeof(chunkModel)); strncpy( useModel, damageModel, sizeof(useModel)); + + // Posto : Small 'fix' to make these breakable , models/map_objects/imp_mine/crate.md3 + if (cg_baseGameFixes.integer) + { + if (strcmp(ent->model, "models/map_objects/imp_mine/crate.md3") == 0) + { + G_SpawnInt("health", "80", &ent->health); + G_SpawnInt("splashRadius", "80", &ent->splashRadius); + G_SpawnInt("splashDamage", "40", &ent->splashDamage); + //ent->s.modelindex = G_ModelIndex("models/map_objects/imp_mine/crate_open.md3"); + ent->fxID = G_EffectIndex("thermal/explosion"); // FIXME: temp + G_EffectIndex("env/crystal_crate"); + G_SoundIndex("sound/weapons/explosions/cargoexplode.wav"); + VectorSet(ent->mins, -34, -34, 0); + VectorSet(ent->maxs, 34, 34, 44); + //Blocks movement + ent->contents = CONTENTS_SOLID | CONTENTS_OPAQUE | CONTENTS_BODY | CONTENTS_MONSTERCLIP | CONTENTS_BOTCLIP;//Was CONTENTS_SOLID, but only architecture should be this + /* + if (ent->spawnflags & 1) // non-solid + { // Override earlier contents flag... + //Can only be shot + ent->contents = CONTENTS_SHOTCLIP; + } + */ + ent->takedamage = qtrue; + G_SetOrigin(ent, ent->s.origin); + VectorCopy(ent->s.angles, ent->s.apos.trBase); + gi.linkentity(ent); + ent->e_PainFunc = painF_CrystalCratePain; + if (ent->targetname) + { + ent->e_UseFunc = useF_misc_use; + } + ent->material = MAT_CRATE2; + ent->e_DieFunc = dieF_misc_model_breakable_die; + return; // We don't want to do anything else + } + } if (ent->takedamage) { //Dead/damaged model diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index d6f7086a..51e866f7 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -23,6 +23,8 @@ extern cvar_t *g_spskill; // Randomizer extern vmCvar_t cg_enableRandomizer; +// Base game fixes +extern vmCvar_t cg_baseGameFixes; /* @@ -842,6 +844,22 @@ void FinishSpawningItem( gentity_t *ent ) { } } + // Base game fixe : in order to get all pickups in ns_starpad, we have to change the two metallic ammo to something else + if (cg_baseGameFixes.integer) + { + if ((strcmp(level.mapname, "ns_starpad")) == 0) + { + if (item->giTag == 4 && item->giType == 2) // Metal ammo + { + item = bg_itemlist + ITM_AMMO_POWERCELL_PICKUP; + //item = bg_itemlist + ITM_BRYAR_PISTOL_PICKUP; + ent->classname == item->classname; + ent->item = item; + } + } + } + + // Randomizer : after getting the item from bg_itemlist, we can finally randomize it here, because every items goes into this function and not only "gun rack" gitem_t* itemNew; gitem_t* itemOld; // So that we have a copy of this, for debugging purpose diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index fb79ee4e..037f1fe2 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -8641,4 +8641,4 @@ void WP_InitForcePowers( gentity_t *ent ) } ent->client->ps.forceGripEntityNum = ENTITYNUM_NONE; } -} \ No newline at end of file +} From 441107c562cb036ed9e62cdd310b36b34e630607 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 16 Dec 2024 11:48:57 +0000 Subject: [PATCH 40/62] NPC Behaviour fixes to allow any NPC to take any slot in any map (#4) * Allow all NPCs to drop keys safely, prevent targeting of neutral entities, ensure NPC team is respected after randomization * Edge case handling for missing NPC_class (morgankatarn), Correct weapon spawning for randomised NPCs, handle missing animation for NPC type * Add swamptrooper team and fix ignore enemies flag * Check for enableRandomizer in NPC_BSFollowLeader * Ensure remaining changes respect cg_enableRandomizer * Correct whitespace only changes and remove no weapons spawns * Fix issue assigning leader to some cutscene NPCs causing them to not spawn correctly and softlock, assign weapons to all NPCs, fix issue removing non-existing weapons, ensure timer stops regardless of NPC spawned in final desanns place * Fix additional issue with missing anims, correctly target desann for timer end, fix issue assigning lightsabers to chars not intended to wield them * fix issue trying to give a saber to NPC with no attachment point fix issue assigning correct team to imperial protocol droids fix issue with sabers allowing NPCs to target nothing and cause a crash * unfuck git for prev NPC fixes * Add exception to saber block for end thugs on ns_starpad, couple of null safety checks, allow some more npcs to be randomized * Cleanup and remove abandoned ideas --- code/game/AI_Jedi.cpp | 5 + code/game/NPC_behavior.cpp | 214 +++++++ code/game/NPC_combat.cpp | 12 +- code/game/NPC_reactions.cpp | 18 +- code/game/NPC_spawn.cpp | 869 ++++++++++++++++------------ code/game/Q3_Interface.cpp | 15 +- code/game/bg_pmove.cpp | 6 + code/game/bg_slidemove.cpp | 7 + code/game/g_combat.cpp | 4 +- code/game/g_main.cpp | 6 +- code/game/g_missile.cpp | 5 + code/game/wp_saber.cpp | 31 +- code/randomizer/RandomizerUtils.cpp | 105 +++- code/randomizer/RandomizerUtils.h | 2 + 14 files changed, 922 insertions(+), 377 deletions(-) diff --git a/code/game/AI_Jedi.cpp b/code/game/AI_Jedi.cpp index c683ef39..14f9b825 100644 --- a/code/game/AI_Jedi.cpp +++ b/code/game/AI_Jedi.cpp @@ -13,6 +13,7 @@ extern qboolean InFront( vec3_t spot, vec3_t from, vec3_t fromAngles, float thre extern void G_StartMatrixEffect( gentity_t *ent, qboolean falling = qfalse, int length = 1000 ); extern cvar_t *g_saberRealisticCombat; extern cvar_t *d_slowmodeath; +extern vmCvar_t cg_enableRandomizer; #define MAX_VIEW_DIST 2048 #define MAX_VIEW_SPEED 100 @@ -3290,6 +3291,10 @@ static void Jedi_CombatTimersUpdate( int enemy_dist ) NPC->client->ps.forcePowerDebounce[FP_SABER_DEFENSE] = level.time + 500; } */ + // targeting an invalid enemy + if (cg_enableRandomizer.integer && (!NPC->enemy || !NPC->enemy->client)) { + return; + } if ( NPC->enemy && PM_SaberInKnockaway( NPC->enemy->client->ps.saberMove ) ) {//advance! Jedi_Aggression( NPC, 1 );//get closer diff --git a/code/game/NPC_behavior.cpp b/code/game/NPC_behavior.cpp index 07d5ad88..31163482 100644 --- a/code/game/NPC_behavior.cpp +++ b/code/game/NPC_behavior.cpp @@ -12,6 +12,7 @@ we need it... #include "Q3_Interface.h" extern cvar_t *g_AIsurrender; +extern vmCvar_t cg_enableRandomizer; extern CNavigator navigator; extern qboolean showBBoxes; static vec3_t NPCDEBUG_BLUE = {0.0, 0.0, 1.0}; @@ -519,6 +520,213 @@ void NPC_BSSleep( void ) } extern qboolean NPC_MoveDirClear( int forwardmove, int rightmove, qboolean reset ); +//Fixes incorrect flag checks for SVF_IGNORE_ENEMIES which prevent stormtroopers from correctly aggroing +void NPC_BSFollowLeaderRandomizer(void) +{ + vec3_t vec; + float leaderDist; + visibility_t leaderVis; + int curAnim; + + if (!NPC->client->leader) + {//ok, stand guard until we find an enemy + if (NPCInfo->tempBehavior == BS_HUNT_AND_KILL) + { + NPCInfo->tempBehavior = BS_DEFAULT; + } + else + { + NPCInfo->tempBehavior = BS_STAND_GUARD; + NPC_BSStandGuard(); + } + return; + } + + if (!NPC->enemy && ~NPCInfo->scriptFlags & SVF_IGNORE_ENEMIES) //Only look for an enemy if ignore enemies is not set + {//no enemy, find one + NPC_CheckEnemy(NPCInfo->confusionTime < level.time, qfalse);//don't find new enemy if this is tempbehav + if (NPC->enemy) + {//just found one + NPCInfo->enemyCheckDebounceTime = level.time + Q_irand(3000, 10000); + } + else + { + if (!(NPCInfo->scriptFlags & SCF_IGNORE_ALERTS)) + { + int eventID = NPC_CheckAlertEvents(qtrue, qtrue); + if (level.alertEvents[eventID].level >= AEL_SUSPICIOUS && (NPCInfo->scriptFlags & SCF_LOOK_FOR_ENEMIES)) + { + NPCInfo->lastAlertID = level.alertEvents[eventID].ID; + if (!level.alertEvents[eventID].owner || + !level.alertEvents[eventID].owner->client || + level.alertEvents[eventID].owner->health <= 0 || + level.alertEvents[eventID].owner->client->playerTeam != NPC->client->enemyTeam) + {//not an enemy + } + else + { + //FIXME: what if can't actually see enemy, don't know where he is... should we make them just become very alert and start looking for him? Or just let combat AI handle this... (act as if you lost him) + G_SetEnemy(NPC, level.alertEvents[eventID].owner); + NPCInfo->enemyCheckDebounceTime = level.time + Q_irand(3000, 10000); + NPCInfo->enemyLastSeenTime = level.time; + TIMER_Set(NPC, "attackDelay", Q_irand(500, 1000)); + } + } + + } + } + if (!NPC->enemy) + { + if (NPC->client->leader + && NPC->client->leader->enemy + && NPC->client->leader->enemy != NPC + && ((NPC->client->leader->enemy->client && NPC->client->leader->enemy->client->playerTeam == NPC->client->enemyTeam) + || (NPC->client->leader->enemy->svFlags & SVF_NONNPC_ENEMY && NPC->client->leader->enemy->noDamageTeam == NPC->client->enemyTeam)) + && NPC->client->leader->enemy->health > 0) + { + G_SetEnemy(NPC, NPC->client->leader->enemy); + NPCInfo->enemyCheckDebounceTime = level.time + Q_irand(3000, 10000); + NPCInfo->enemyLastSeenTime = level.time; + } + } + } + else if (~NPCInfo->scriptFlags & SVF_IGNORE_ENEMIES) + { + if (NPC->enemy->health <= 0 || (NPC->enemy->flags & FL_NOTARGET)) + { + G_ClearEnemy(NPC); + if (NPCInfo->enemyCheckDebounceTime > level.time + 1000) + { + NPCInfo->enemyCheckDebounceTime = level.time + Q_irand(1000, 2000); + } + } + else if (NPC->client->ps.weapon && NPCInfo->enemyCheckDebounceTime < level.time) + { + NPC_CheckEnemy((NPCInfo->confusionTime < level.time || NPCInfo->tempBehavior != BS_FOLLOW_LEADER), qfalse);//don't find new enemy if this is tempbehav + } + } + + if (NPC->enemy && NPC->client->ps.weapon) + {//If have an enemy, face him and fire + if (NPC->client->ps.weapon == WP_SABER)//|| NPCInfo->confusionTime>level.time ) + {//lightsaber user or charmed enemy + if (NPCInfo->tempBehavior != BS_FOLLOW_LEADER) + {//not already in a temp bState + //go after the guy + NPCInfo->tempBehavior = BS_HUNT_AND_KILL; + NPC_UpdateAngles(qtrue, qtrue); + return; + } + } + + enemyVisibility = NPC_CheckVisibility(NPC->enemy, CHECK_FOV | CHECK_SHOOT);//CHECK_360|CHECK_PVS| + if (enemyVisibility > VIS_PVS) + {//face + vec3_t enemy_org, muzzle, delta, angleToEnemy; + float distanceToEnemy; + + CalcEntitySpot(NPC->enemy, SPOT_HEAD, enemy_org); + NPC_AimWiggle(enemy_org); + + CalcEntitySpot(NPC, SPOT_WEAPON, muzzle); + + VectorSubtract(enemy_org, muzzle, delta); + vectoangles(delta, angleToEnemy); + distanceToEnemy = VectorNormalize(delta); + + NPCInfo->desiredYaw = angleToEnemy[YAW]; + NPCInfo->desiredPitch = angleToEnemy[PITCH]; + NPC_UpdateFiringAngles(qtrue, qtrue); + + if (enemyVisibility >= VIS_SHOOT) + {//shoot + NPC_AimAdjust(2); + if (NPC_GetHFOVPercentage(NPC->enemy->currentOrigin, NPC->currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.hfov) > 0.6f + && NPC_GetHFOVPercentage(NPC->enemy->currentOrigin, NPC->currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.vfov) > 0.5f) + {//actually withing our front cone + WeaponThink(qtrue); + } + } + else + { + NPC_AimAdjust(1); + } + + //NPC_CheckCanAttack(1.0, qfalse); + } + else + { + NPC_AimAdjust(-1); + } + } + else + {//FIXME: combine with vector calc below + vec3_t head, leaderHead, delta, angleToLeader; + + CalcEntitySpot(NPC->client->leader, SPOT_HEAD, leaderHead); + CalcEntitySpot(NPC, SPOT_HEAD, head); + VectorSubtract(leaderHead, head, delta); + vectoangles(delta, angleToLeader); + VectorNormalize(delta); + NPC->NPC->desiredYaw = angleToLeader[YAW]; + NPC->NPC->desiredPitch = angleToLeader[PITCH]; + + NPC_UpdateAngles(qtrue, qtrue); + } + + //leader visible? + leaderVis = NPC_CheckVisibility(NPC->client->leader, CHECK_PVS | CHECK_360 | CHECK_SHOOT);// ent->e_UseFunc = useF_NULL; + + + //Follow leader, stay within visibility and a certain distance, maintain a distance from. + curAnim = NPC->client->ps.legsAnim; + if (curAnim != BOTH_ATTACK1 && curAnim != BOTH_ATTACK2 && curAnim != BOTH_ATTACK3 && curAnim != BOTH_MELEE1 && curAnim != BOTH_MELEE2) + {//Don't move toward leader if we're in a full-body attack anim + //FIXME, use IdealDistance to determine if we need to close distance + float followDist = 96.0f;//FIXME: If there are enmies, make this larger? + float backupdist, walkdist, minrundist; + + if (NPCInfo->followDist) + { + followDist = NPCInfo->followDist; + } + backupdist = followDist / 2.0f; + walkdist = followDist * 0.83; + minrundist = followDist * 1.33; + + VectorSubtract(NPC->client->leader->currentOrigin, NPC->currentOrigin, vec); + leaderDist = VectorLength(vec);//FIXME: make this just nav distance? + //never get within their radius horizontally + vec[2] = 0; + float leaderHDist = VectorLength(vec); + if (leaderHDist > backupdist && (leaderVis != VIS_SHOOT || leaderDist > walkdist)) + {//We should close in? + NPCInfo->goalEntity = NPC->client->leader; + + NPC_SlideMoveToGoal(); + if (leaderVis == VIS_SHOOT && leaderDist < minrundist) + { + ucmd.buttons |= BUTTON_WALKING; + } + } + else if (leaderDist < backupdist) + {//We should back off? + NPCInfo->goalEntity = NPC->client->leader; + NPC_SlideMoveToGoal(); + + //reversing direction + ucmd.forwardmove = -ucmd.forwardmove; + ucmd.rightmove = -ucmd.rightmove; + VectorScale(NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir); + }//otherwise, stay where we are + //check for do not enter and stop if there's one there... + if (ucmd.forwardmove || ucmd.rightmove || VectorCompare(vec3_origin, NPC->client->ps.moveDir)) + { + NPC_MoveDirClear(ucmd.forwardmove, ucmd.rightmove, qtrue); + } + } +} + void NPC_BSFollowLeader (void) { vec3_t vec; @@ -526,6 +734,12 @@ void NPC_BSFollowLeader (void) visibility_t leaderVis; int curAnim; + if (cg_enableRandomizer.integer) + { + NPC_BSFollowLeaderRandomizer(); + return; + } + if ( !NPC->client->leader ) {//ok, stand guard until we find an enemy if( NPCInfo->tempBehavior == BS_HUNT_AND_KILL ) diff --git a/code/game/NPC_combat.cpp b/code/game/NPC_combat.cpp index f11033df..f70b9289 100644 --- a/code/game/NPC_combat.cpp +++ b/code/game/NPC_combat.cpp @@ -18,6 +18,7 @@ extern int NAV_FindClosestWaypointForPoint( vec3_t point ); extern int NAV_GetNearestNode( gentity_t *self, int lastNode ); extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponModel ); extern qboolean PM_DroidMelee( int npc_class ); +extern vmCvar_t cg_enableRandomizer; extern CNavigator navigator; @@ -353,6 +354,10 @@ void G_SetEnemy( gentity_t *self, gentity_t *enemy ) #ifdef _DEBUG if ( self->s.number ) { + //Debug convenience, this doesn't change anything in FinalBuild but prevents popups when debugging + if (cg_enableRandomizer.integer && enemy == self) { + return; + } assert( enemy != self ); } #endif// _DEBUG @@ -1827,7 +1832,12 @@ gentity_t *NPC_CheckEnemy( qboolean findNew, qboolean tooFarOk, qboolean setEnem if ( NPC->enemy ) { - if ( !NPC->enemy->inuse )//|| NPC->enemy == NPC )//wtf? NPCs should never get mad at themselves! + //If we're targeting a neutral character (e.g. player during artus_detention officer escort) - don't + //Amber TODO: We still get aggro'd to here, annoying + if (cg_enableRandomizer.integer && NPC->enemy->client && NPC->enemy->client->playerTeam == TEAM_NEUTRAL) + { + G_ClearEnemy(NPC); + } else if ( !NPC->enemy->inuse )//|| NPC->enemy == NPC )//wtf? NPCs should never get mad at themselves! { if ( setEnemy ) { diff --git a/code/game/NPC_reactions.cpp b/code/game/NPC_reactions.cpp index c1da586a..27faafcc 100644 --- a/code/game/NPC_reactions.cpp +++ b/code/game/NPC_reactions.cpp @@ -34,6 +34,7 @@ extern qboolean PM_RollingAnim( int anim ); extern qboolean PM_InCartwheel( int anim ); extern cvar_t *g_spskill; +extern vmCvar_t cg_enableRandomizer; extern int teamLastEnemyTime[]; extern qboolean stop_icarus; extern int killPlayerTimer; @@ -545,11 +546,18 @@ void NPC_Touch(gentity_t *self, gentity_t *other, trace_t *trace) } if ( keyTaken ) {//remove my key - gi.G2API_SetSurfaceOnOff( &self->ghoul2[self->playerModel], "l_arm_key", 0x00000002 ); - self->message = NULL; - //FIXME: temp pickup sound - G_Sound( player, G_SoundIndex( "sound/weapons/key_pkup.wav" ) ); - //FIXME: need some event to pass to cgame for sound/graphic/message? + if (cg_enableRandomizer.integer && self->playerModel == -1) { + //Some NPCs do not leave a model behind after death - so don't try to remove it + self->message = NULL; + G_Sound(player, G_SoundIndex("sound/weapons/key_pkup.wav")); + } + else { + gi.G2API_SetSurfaceOnOff(&self->ghoul2[self->playerModel], "l_arm_key", 0x00000002); + self->message = NULL; + //FIXME: temp pickup sound + G_Sound(player, G_SoundIndex("sound/weapons/key_pkup.wav")); + //FIXME: need some event to pass to cgame for sound/graphic/message? + } } //FIXME: temp message gi.SendServerCommand( NULL, text ); diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 37b6cb7f..81e034fa 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -170,15 +170,215 @@ touchFunc_t NPC_TouchFunc( gentity_t *ent ) return touchF_NPC_Touch; } +extern void G_CreateG2AttachedWeaponModel(gentity_t* ent, const char* weaponModel); +//Easier to break this into another function as I refactored a bit to make it cleaner +void NPC_SetMiscDefaultDataRandomizer(gentity_t* ent) +{ + if (ent->spawnflags & SFB_CINEMATIC) + {//if a cinematic guy, default us to wait bState + ent->NPC->behaviorState = BS_CINEMATIC; + } + switch (ent->client->playerTeam) { + case TEAM_PLAYER: + ent->client->enemyTeam = TEAM_ENEMY; + break; + case TEAM_ENEMY: + ent->client->enemyTeam = TEAM_PLAYER; + break; + default: //TODO: AMBER Figure out how to handle this properly + ent->client->enemyTeam = TEAM_FREE; + } + //***I'm not sure whether I should leave this as a TEAM_ switch, I think NPC_class may be more appropriate - dmv + //Amber - whoever dmv is they're right, this should be based on class + switch (ent->client->NPC_class) { + case CLASS_SEEKER: + ent->NPC->defaultBehavior = BS_DEFAULT; + ent->client->ps.gravity = 0; + ent->svFlags |= SVF_CUSTOM_GRAVITY; + ent->NPC->stats.moveType = MT_FLYSWIM; + ent->count = 30; // SEEKER shot ammo count + return; + case CLASS_PROBE: + case CLASS_REMOTE: + case CLASS_INTERROGATOR: + case CLASS_SENTRY: + ent->NPC->defaultBehavior = BS_DEFAULT; + ent->client->ps.gravity = 0; + ent->svFlags |= SVF_CUSTOM_GRAVITY; + ent->NPC->stats.moveType = MT_FLYSWIM; + break; + case CLASS_JEDI: + case CLASS_LUKE: + case CLASS_TAVION: + case CLASS_REBORN: + case CLASS_DESANN: + case CLASS_SHADOWTROOPER: + //All saber wielders + ent->client->ps.saberActive = qfalse; + ent->client->ps.saberLength = 0; + WP_SaberInitBladeData(ent); + G_CreateG2AttachedWeaponModel(ent, ent->client->ps.saberModel); + //ent->client->enemyTeam = TEAM_ENEMY; + WP_InitForcePowers(ent); + Jedi_ClearTimers(ent); + if (ent->spawnflags & JSF_AMBUSH) + {//ambusher + ent->NPC->scriptFlags |= SCF_IGNORE_ALERTS; + ent->client->noclip = qtrue;//hang + } + break; + case CLASS_GONK: + // I guess we generically make them player usable + ent->svFlags |= SVF_PLAYER_USABLE; + + // Not even sure if we want to give different levels of batteries? ...Or even that these are the values we'd want to use. + switch (g_spskill->integer) + { + case 0: // EASY + ent->client->ps.batteryCharge = MAX_BATTERIES * 0.8f; + break; + case 1: // MEDIUM + ent->client->ps.batteryCharge = MAX_BATTERIES * 0.75f; + break; + default: + case 2: // HARD + ent->client->ps.batteryCharge = MAX_BATTERIES * 0.5f; + break; + } + break; + case CLASS_R2D2: // No weapons for astromech droids please + case CLASS_R5D2: + break; + default: + if (ent->client->ps.weapon != WP_NONE) + { + G_CreateG2AttachedWeaponModel(ent, weaponData[ent->client->ps.weapon].weaponMdl); + } + if (RandomizerUtils::GetClassTeamByClass(ent->client->NPC_class) == TEAM_PLAYER) //Any other NPCs which would normally be friendsly + { + switch (ent->client->ps.weapon) + { + case WP_BRYAR_PISTOL://FIXME: new weapon: imp blaster pistol + case WP_BLASTER_PISTOL: + case WP_DISRUPTOR: + case WP_BOWCASTER: + case WP_REPEATER: + case WP_DEMP2: + case WP_FLECHETTE: + case WP_ROCKET_LAUNCHER: + default: + break; + case WP_THERMAL: + case WP_BLASTER: + //FIXME: health in NPCs.cfg, and not all blaster users are stormtroopers + //ent->health = 25; + //FIXME: not necc. a ST + ST_ClearTimers(ent); + if (ent->NPC->rank >= RANK_LT || ent->client->ps.weapon == WP_THERMAL) + {//officers, grenade-throwers use alt-fire + //ent->health = 50; + ent->NPC->scriptFlags |= SCF_ALT_FIRE; + } + break; + } + } + else if (RandomizerUtils::GetClassTeamByClass(ent->client->NPC_class) == TEAM_ENEMY) { //Any other NPCs which would normally be enemies + { + ent->NPC->defaultBehavior = BS_DEFAULT; + if (ent->client->NPC_class == CLASS_SHADOWTROOPER) + {//FIXME: a spawnflag? + Jedi_Cloak(ent); + } + + G_CreateG2AttachedWeaponModel(ent, weaponData[ent->client->ps.weapon].weaponMdl); + switch (ent->client->ps.weapon) + { + case WP_BRYAR_PISTOL: + break; + case WP_BLASTER_PISTOL: + break; + case WP_DISRUPTOR: + //Sniper + ent->NPC->scriptFlags |= SCF_ALT_FIRE;//FIXME: use primary fire sometimes? Up close? Different class of NPC? + break; + case WP_BOWCASTER: + break; + case WP_REPEATER: + //machine-gunner + break; + case WP_DEMP2: + break; + case WP_FLECHETTE: + //shotgunner + if (!Q_stricmp("stofficeralt", ent->NPC_type)) + { + ent->NPC->scriptFlags |= SCF_ALT_FIRE; + } + break; + case WP_ROCKET_LAUNCHER: + break; + case WP_THERMAL: + //Gran, use main, bouncy fire +// ent->NPC->scriptFlags |= SCF_ALT_FIRE; + break; + case WP_MELEE: + break; + default: + case WP_BLASTER: + //FIXME: health in NPCs.cfg, and not all blaster users are stormtroopers + //FIXME: not necc. a ST + ST_ClearTimers(ent); + if (ent->NPC->rank >= RANK_COMMANDER) + {//commanders use alt-fire + ent->NPC->scriptFlags |= SCF_ALT_FIRE; + } + if (!Q_stricmp("rodian2", ent->NPC_type)) + { + ent->NPC->scriptFlags |= SCF_ALT_FIRE; + } + break; + } + if (!Q_stricmp("galak_mech", ent->NPC_type)) + {//starts with armor + NPC_GalakMech_Init(ent); + } + } + + } + + //Extra stuff for cinematic chars and behaviour set for friendly NPCS + if (ent->client->NPC_class == CLASS_KYLE || (ent->spawnflags & SFB_CINEMATIC)) + { + ent->NPC->defaultBehavior = BS_CINEMATIC; + } + else if (ent->client->playerTeam == TEAM_PLAYER) + { + ent->NPC->defaultBehavior = BS_FOLLOW_LEADER; + ent->client->leader = &g_entities[0]; + } + + //Shields for ATSTs/Mark1s + if (ent->client->NPC_class == CLASS_ATST || ent->client->NPC_class == CLASS_MARK1) // chris/steve/kevin requested that the mark1 be shielded also + { + ent->flags |= (FL_SHIELDED | FL_NO_KNOCKBACK); + } + } +} + /* ------------------------- NPC_SetMiscDefaultData ------------------------- */ -extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponModel ); -void NPC_SetMiscDefaultData( gentity_t *ent ) +void NPC_SetMiscDefaultData(gentity_t* ent) { + if (cg_enableRandomizer.integer) + { + NPC_SetMiscDefaultDataRandomizer(ent); + return; + } + if ( ent->spawnflags & SFB_CINEMATIC ) {//if a cinematic guy, default us to wait bState ent->NPC->behaviorState = BS_CINEMATIC; @@ -280,104 +480,104 @@ void NPC_SetMiscDefaultData( gentity_t *ent ) break; case TEAM_ENEMY: + { + ent->NPC->defaultBehavior = BS_DEFAULT; + if (ent->client->NPC_class == CLASS_SHADOWTROOPER) + {//FIXME: a spawnflag? + Jedi_Cloak(ent); + } + if (ent->client->NPC_class == CLASS_TAVION || + ent->client->NPC_class == CLASS_REBORN || + ent->client->NPC_class == CLASS_DESANN || + ent->client->NPC_class == CLASS_SHADOWTROOPER) { - ent->NPC->defaultBehavior = BS_DEFAULT; - if ( ent->client->NPC_class == CLASS_SHADOWTROOPER ) - {//FIXME: a spawnflag? - Jedi_Cloak( ent ); - } - if( ent->client->NPC_class == CLASS_TAVION || - ent->client->NPC_class == CLASS_REBORN || - ent->client->NPC_class == CLASS_DESANN || - ent->client->NPC_class == CLASS_SHADOWTROOPER ) - { - ent->client->ps.saberActive = qfalse; - ent->client->ps.saberLength = 0; - WP_SaberInitBladeData( ent ); - G_CreateG2AttachedWeaponModel( ent, ent->client->ps.saberModel ); - WP_InitForcePowers( ent ); - ent->client->enemyTeam = TEAM_PLAYER; - Jedi_ClearTimers( ent ); - if ( ent->spawnflags & JSF_AMBUSH ) - {//ambusher - ent->NPC->scriptFlags |= SCF_IGNORE_ALERTS; - ent->client->noclip = qtrue;//hang - } - } - else if( ent->client->NPC_class == CLASS_PROBE || ent->client->NPC_class == CLASS_REMOTE || - ent->client->NPC_class == CLASS_INTERROGATOR || ent->client->NPC_class == CLASS_SENTRY) - { - ent->NPC->defaultBehavior = BS_DEFAULT; - ent->client->ps.gravity = 0; - ent->svFlags |= SVF_CUSTOM_GRAVITY; - ent->NPC->stats.moveType = MT_FLYSWIM; + ent->client->ps.saberActive = qfalse; + ent->client->ps.saberLength = 0; + WP_SaberInitBladeData(ent); + G_CreateG2AttachedWeaponModel(ent, ent->client->ps.saberModel); + WP_InitForcePowers(ent); + ent->client->enemyTeam = TEAM_PLAYER; + Jedi_ClearTimers(ent); + if (ent->spawnflags & JSF_AMBUSH) + {//ambusher + ent->NPC->scriptFlags |= SCF_IGNORE_ALERTS; + ent->client->noclip = qtrue;//hang } - else + } + else if (ent->client->NPC_class == CLASS_PROBE || ent->client->NPC_class == CLASS_REMOTE || + ent->client->NPC_class == CLASS_INTERROGATOR || ent->client->NPC_class == CLASS_SENTRY) + { + ent->NPC->defaultBehavior = BS_DEFAULT; + ent->client->ps.gravity = 0; + ent->svFlags |= SVF_CUSTOM_GRAVITY; + ent->NPC->stats.moveType = MT_FLYSWIM; + } + else + { + G_CreateG2AttachedWeaponModel(ent, weaponData[ent->client->ps.weapon].weaponMdl); + switch (ent->client->ps.weapon) { - G_CreateG2AttachedWeaponModel( ent, weaponData[ent->client->ps.weapon].weaponMdl ); - switch ( ent->client->ps.weapon ) + case WP_BRYAR_PISTOL: + break; + case WP_BLASTER_PISTOL: + break; + case WP_DISRUPTOR: + //Sniper + ent->NPC->scriptFlags |= SCF_ALT_FIRE;//FIXME: use primary fire sometimes? Up close? Different class of NPC? + break; + case WP_BOWCASTER: + break; + case WP_REPEATER: + //machine-gunner + break; + case WP_DEMP2: + break; + case WP_FLECHETTE: + //shotgunner + if (!Q_stricmp("stofficeralt", ent->NPC_type)) { - case WP_BRYAR_PISTOL: - break; - case WP_BLASTER_PISTOL: - break; - case WP_DISRUPTOR: - //Sniper - ent->NPC->scriptFlags |= SCF_ALT_FIRE;//FIXME: use primary fire sometimes? Up close? Different class of NPC? - break; - case WP_BOWCASTER: - break; - case WP_REPEATER: - //machine-gunner - break; - case WP_DEMP2: - break; - case WP_FLECHETTE: - //shotgunner - if ( !Q_stricmp( "stofficeralt", ent->NPC_type ) ) - { - ent->NPC->scriptFlags |= SCF_ALT_FIRE; - } - break; - case WP_ROCKET_LAUNCHER: - break; - case WP_THERMAL: - //Gran, use main, bouncy fire + ent->NPC->scriptFlags |= SCF_ALT_FIRE; + } + break; + case WP_ROCKET_LAUNCHER: + break; + case WP_THERMAL: + //Gran, use main, bouncy fire // ent->NPC->scriptFlags |= SCF_ALT_FIRE; - break; - case WP_MELEE: - break; - default: - case WP_BLASTER: - //FIXME: health in NPCs.cfg, and not all blaster users are stormtroopers - //FIXME: not necc. a ST - ST_ClearTimers( ent ); - if ( ent->NPC->rank >= RANK_COMMANDER ) - {//commanders use alt-fire - ent->NPC->scriptFlags |= SCF_ALT_FIRE; - } - if ( !Q_stricmp( "rodian2", ent->NPC_type ) ) - { - ent->NPC->scriptFlags |= SCF_ALT_FIRE; - } - break; + break; + case WP_MELEE: + break; + default: + case WP_BLASTER: + //FIXME: health in NPCs.cfg, and not all blaster users are stormtroopers + //FIXME: not necc. a ST + ST_ClearTimers(ent); + if (ent->NPC->rank >= RANK_COMMANDER) + {//commanders use alt-fire + ent->NPC->scriptFlags |= SCF_ALT_FIRE; } - if ( !Q_stricmp( "galak_mech", ent->NPC_type ) ) - {//starts with armor - NPC_GalakMech_Init( ent ); + if (!Q_stricmp("rodian2", ent->NPC_type)) + { + ent->NPC->scriptFlags |= SCF_ALT_FIRE; } + break; + } + if (!Q_stricmp("galak_mech", ent->NPC_type)) + {//starts with armor + NPC_GalakMech_Init(ent); } } - break; + } + break; default: break; } - if ( ent->client->NPC_class == CLASS_ATST || ent->client->NPC_class == CLASS_MARK1 ) // chris/steve/kevin requested that the mark1 be shielded also + if (ent->client->NPC_class == CLASS_ATST || ent->client->NPC_class == CLASS_MARK1) // chris/steve/kevin requested that the mark1 be shielded also { - ent->flags |= (FL_SHIELDED|FL_NO_KNOCKBACK); + ent->flags |= (FL_SHIELDED | FL_NO_KNOCKBACK); } } @@ -386,9 +586,198 @@ void NPC_SetMiscDefaultData( gentity_t *ent ) NPC_WeaponsForTeam ------------------------- */ +int NPC_WeaponsForTeamRandomizer(team_t team, int spawnflags, const char* NPC_type) +{ + //*** not sure how to handle this, should I pass in class instead of team and go from there? - dmv + //Amber - damn this dmv person was onto things + + //TODO: Game has these exceptions built in for when certain NPCs are neutral - how to handle? Preserved for now + if (team == TEAM_NEUTRAL) + { + if (Q_stricmp("mark1", NPC_type) == 0) + { + return WP_NONE; + } + if (Q_stricmp("mark2", NPC_type) == 0) + { + return WP_NONE; + } + if (Q_strncmp("ugnaught", NPC_type, 8) == 0) + { + return WP_NONE; + } + if (Q_stricmp("bartender", NPC_type) == 0) + { + return WP_NONE; + } + if (Q_stricmp("morgankatarn", NPC_type) == 0) + { + return WP_NONE; + } + } + + //All Saber Wielders + if (Q_stricmp("tavion", NPC_type) == 0 || + Q_strncmp("reborn", NPC_type, 6) == 0 || + Q_stricmp("desann", NPC_type) == 0 || + Q_strncmp("shadowtrooper", NPC_type, 13) == 0 || + Q_strncmp("jedi", NPC_type, 4) == 0 || + Q_stricmp("luke", NPC_type) == 0) + return (1 << WP_SABER); + + /* + * Okay decision time here. If we ever spawn a non-neutral NPC with no weapon, it will try to set up a saber for them and the game will crash. + * For now, commented out all blocks here with WP_NONE so they fall into the default blaster block. We can have it just not try to set up + * a weapon for NPCs with weapon none if we want to give up being shot at by ugnaughts, droids etc. We could also assign random weapons + * (personally I wanna see someone get shotgunned down by C3PO) + */ + if (Q_strncmp("stofficer", NPC_type, 9) == 0) + { + return (1 << WP_FLECHETTE); + } + if (Q_stricmp("stcommander", NPC_type) == 0) + { + return (1 << WP_REPEATER); + } + if (Q_stricmp("swamptrooper", NPC_type) == 0) + { + return (1 << WP_FLECHETTE); + } + if (Q_stricmp("swamptrooper2", NPC_type) == 0) + { + return (1 << WP_REPEATER); + } + if (Q_stricmp("rockettrooper", NPC_type) == 0) + { + return (1 << WP_ROCKET_LAUNCHER); + } + if (Q_strncmp("shadowtrooper", NPC_type, 13) == 0) + { + return (1 << WP_SABER);//|( 1 << WP_RAPID_CONCUSSION)? + } + if (Q_stricmp("imperial", NPC_type) == 0) + { + return (1 << WP_BLASTER_PISTOL); + } + if (Q_strncmp("impworker", NPC_type, 9) == 0) + { + return (1 << WP_BLASTER_PISTOL); + } + if (Q_stricmp("stormpilot", NPC_type) == 0) + { + return (1 << WP_BLASTER_PISTOL); + } + if (Q_stricmp("galak", NPC_type) == 0) + { + return (1 << WP_BLASTER); + } + if (Q_stricmp("galak_mech", NPC_type) == 0) + { + return (1 << WP_REPEATER); + } + //if (Q_strncmp("ugnaught", NPC_type, 8) == 0) + //{ + // return WP_NONE; + //} + if (Q_stricmp("granshooter", NPC_type) == 0) + { + return (1 << WP_BLASTER); + } + if (Q_stricmp("granboxer", NPC_type) == 0) + { + return (1 << WP_MELEE); + } + if (Q_strncmp("gran", NPC_type, 4) == 0) + { + return ((1 << WP_THERMAL) | (1 << WP_MELEE)); + } + if (Q_stricmp("rodian", NPC_type) == 0) + { + return (1 << WP_DISRUPTOR); + } + if (Q_stricmp("rodian2", NPC_type) == 0) + { + return (1 << WP_BLASTER); + } + if ((Q_stricmp("interrogator", NPC_type) == 0) || (Q_stricmp("sentry", NPC_type) == 0)) + { + return WP_NONE; + } + if (Q_strncmp("weequay", NPC_type, 7) == 0) + { + return (1 << WP_BOWCASTER);//|( 1 << WP_STAFF )(FIXME: new weap?) + } + if (Q_stricmp("impofficer", NPC_type) == 0) + { + return (1 << WP_BLASTER); + } + if (Q_stricmp("impcommander", NPC_type) == 0) + { + return (1 << WP_BLASTER); + } + if ((Q_stricmp("probe", NPC_type) == 0) || (Q_stricmp("seeker", NPC_type) == 0)) + { + return (1 << WP_BOT_LASER); + } + if (Q_stricmp("remote", NPC_type) == 0) + { + return (1 << WP_BOT_LASER); + } + if (Q_stricmp("trandoshan", NPC_type) == 0) + { + return (1 << WP_REPEATER); + } + if (Q_stricmp("atst", NPC_type) == 0) + { + return ((1 << WP_ATST_MAIN) | (1 << WP_ATST_SIDE)); + } + if (Q_stricmp("mark1", NPC_type) == 0) + { + return (1 << WP_BOT_LASER); + } + if (Q_stricmp("mark2", NPC_type) == 0) + { + return (1 << WP_BOT_LASER); + } + if (Q_stricmp("minemonster", NPC_type) == 0) + { + return ((1 << WP_MELEE)); + } + if (Q_stricmp("howler", NPC_type) == 0) + { + return ((1 << WP_MELEE)); + } + //if (Q_strncmp("prisoner", NPC_type, 8) == 0) + //{ + // return WP_NONE; + //} + if (Q_strncmp("bespincop", NPC_type, 9) == 0) + { + return (1 << WP_BLASTER_PISTOL); + } + //if (Q_stricmp("MonMothma", NPC_type) == 0) + //{ + // return WP_NONE; + //} + if (!Q_stricmp("protocol", NPC_type)) { + return 1 << WP_STUN_BATON; + } + if (spawnflags & SFB_RIFLEMAN) + return (1 << WP_REPEATER); + + if (spawnflags & SFB_PHASER) + return (1 << WP_BLASTER_PISTOL); + + //Still default to blaster if we're not explicitly set (Stormtroopers, rebels) + return (1 << WP_BLASTER); //We might be giving droids (R2, R4, Protocol) blasters here, should we keep? +} int NPC_WeaponsForTeam( team_t team, int spawnflags, const char *NPC_type ) { + if (cg_enableRandomizer.integer) + { + return NPC_WeaponsForTeamRandomizer(team, spawnflags, NPC_type); + } //*** not sure how to handle this, should I pass in class instead of team and go from there? - dmv switch(team) { @@ -1299,6 +1688,14 @@ void NPC_Spawn_Go( gentity_t *ent ) newent->classname = "NPC"; // newent->svFlags |= SVF_NOPUSH; } + else if (cg_enableRandomizer.integer) { + if (!Q_stricmp("protocol_imp", ent->NPC_type)) { + //Imperial protocol droids share a class with C3PO but should be enemy team + newent->client->playerTeam = TEAM_ENEMY; + } else { + newent->client->playerTeam = RandomizerUtils::GetClassTeamByClassname(ent->classname); + } + } } //===================================================================== //set the info we want @@ -2642,9 +3039,15 @@ Seeker Droid - floating round droids that shadow troopers spawn */ void SP_NPC_Droid_Seeker( gentity_t *self) { + //Just spawn the other kind if it should be an enemy + if (cg_enableRandomizer.integer && RandomizerUtils::GetClassTeamByClassname(self->classname) == TEAM_ENEMY) { + SP_NPC_Droid_Remote(self); + return; + } + self->NPC_type = "seeker"; - SP_NPC_spawner( self ); + SP_NPC_spawner(self); NPC_Seeker_Precache(); } @@ -2983,7 +3386,7 @@ void SP_NPC_Spawn_Random(gentity_t* self) rng = rand() % 50; } - switch (rng) + switch (rng) { case 0: SP_NPC_Kyle(self); @@ -3005,7 +3408,7 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_MonMothma(self); PopulateNPCTab(rng); break; - case 5: // Desann and Tavion are too hard to handle, buuuut we have force in earlt levels now + case 5: // Desann and Tavion are too hard to handle, but they should behave now SP_NPC_Tavion(self); PopulateNPCTab(rng); //SP_NPC_Spawn_Random(self); @@ -3018,7 +3421,7 @@ void SP_NPC_Spawn_Random(gentity_t* self) SP_NPC_Galak(self); PopulateNPCTab(rng); break; - case 8: // Desann and Tavion are too hard to handle, buuuut we have force in earlt levels now + case 8: // Desann and Tavion are too hard to handle, but they should behave now SP_NPC_Desann(self); PopulateNPCTab(rng); //SP_NPC_Spawn_Random(self); @@ -3192,9 +3595,8 @@ void SP_NPC_Spawn_Random(gentity_t* self) PopulateNPCTab(rng); break; case 48: // Spawning this droid on kejim_base is making the game crash ???? - //SP_NPC_Droid_R5D2(self); - //PopulateNPCTab(rng); - SP_NPC_Spawn_Random(self); + SP_NPC_Droid_R5D2(self); + PopulateNPCTab(rng); break; case 49: SP_NPC_Droid_Protocol(self); @@ -3207,63 +3609,6 @@ void SP_NPC_Spawn_Random(gentity_t* self) } } -void SpawnValidKeyholder(gentity_t* self) // Presumably an humanoid, since droids crashes the game. -{ - // X being the number of valid NPC that can hold a key - int rng = rand() % 5; - - // In the meantime, here is Kyle - //SP_NPC_Kyle(self); - - switch (rng) - { - case 0: - break; - default: - break; - } -} - -bool CheckForceSpawn(gentity_t* self, char whatWeCompare[], char whoToSpawn[]) // Used in maps when we will spawn something -{ - // It's either NPC_targetname or targetname, check for both and return when done. - if (self->NPC_targetname) // Check if NULL - { - if (strncmp(self->NPC_targetname, whatWeCompare, strlen(self->NPC_targetname)) == 0) // Got it, we have to spawn this entity - { - // Temporary : just spawn the 'normal' NPC - if (strcmp(whoToSpawn, "Rebel") == 0) SP_NPC_Rebel(self); - if (strcmp(whoToSpawn, "Imperial") == 0) SP_NPC_Imperial(self); - if (strcmp(whoToSpawn, "Rodian") == 0) SP_NPC_Rodian(self); - if (strcmp(whoToSpawn, "Stormtrooper") == 0) SP_NPC_Stormtrooper(self); - if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); - if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); - if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); - if (strcmp(whoToSpawn, "Shadowtrooper") == 0) SP_NPC_ShadowTrooper(self); - - return true; // True, we forcefully spawned something - } - } - if (self->targetname) // Check if NULL - { - if (strncmp(self->targetname, whatWeCompare, strlen(self->targetname)) == 0) // Got it, we have to spawn this entity - { - // Temporary : just spawn the 'normal' NPC - if (strcmp(whoToSpawn, "Rebel") == 0) SP_NPC_Rebel(self); - if (strcmp(whoToSpawn, "Imperial") == 0) SP_NPC_Imperial(self); - if (strcmp(whoToSpawn, "Rodian") == 0) SP_NPC_Rodian(self); - if (strcmp(whoToSpawn, "Stormtrooper") == 0) SP_NPC_Stormtrooper(self); - if (strcmp(whoToSpawn, "Weequay") == 0) SP_NPC_Weequay(self); - if (strcmp(whoToSpawn, "Gran") == 0) SP_NPC_Gran(self); - if (strcmp(whoToSpawn, "Reborn") == 0) SP_NPC_Reborn(self); - if (strcmp(whoToSpawn, "Shadowtrooper") == 0) SP_NPC_ShadowTrooper(self); - - return true; // True, we forcefully spawned something - } - } - return false; // False, it's not a forced spawn -} - // If the Randomizer is disabled, just a bit of process time is added at every check, but at least it should be comptable with the standard SpeedOutcast void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle { @@ -3279,7 +3624,7 @@ void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Lando(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Lando(self); } @@ -3288,7 +3633,7 @@ void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Jan(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Jan(self); } @@ -3297,7 +3642,7 @@ void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Luke(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Luke(self); } @@ -3306,7 +3651,7 @@ void SP_NPC_MonMothma_Random(gentity_t* self) // MonMothma should always spawn a if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_MonMothma(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_MonMothma(self); } @@ -3315,7 +3660,7 @@ void SP_NPC_Tavion_Random(gentity_t* self) // Tavion should always spawn as Tavi if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Tavion(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Tavion(self); } @@ -3324,7 +3669,7 @@ void SP_NPC_Reelo_Random(gentity_t* self) // Reelo should always spawn as Reelo if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Reelo(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Reelo(self); } @@ -3333,7 +3678,7 @@ void SP_NPC_Galak_Random(gentity_t* self) // Galak should always spawn as Galak if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Galak(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Galak(self); } @@ -3342,7 +3687,7 @@ void SP_NPC_Desann_Random(gentity_t* self) // Desann should always spawn as Desa if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Desann(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Desann(self); } @@ -3351,7 +3696,7 @@ void SP_NPC_Bartender_Random(gentity_t* self) // Bartender should always spawn a if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Bartender(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Bartender(self); } @@ -3360,7 +3705,7 @@ void SP_NPC_MorganKatarn_Random(gentity_t* self) // Morgarn should always spawn if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_MorganKatarn(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_MorganKatarn(self); } @@ -3378,7 +3723,7 @@ void SP_NPC_Prisoner_Random(gentity_t* self) // Prisoners should spawn as themse if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Prisoner(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Prisoner(self); } @@ -3387,10 +3732,6 @@ void SP_NPC_Rebel_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The rebel being shot on has to be constant - { - if (CheckForceSpawn(self, "rebel_target", "Rebel")) return; - } SP_NPC_Spawn_Random(self); } else SP_NPC_Rebel(self); @@ -3400,32 +3741,6 @@ void SP_NPC_Stormtrooper_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The stormtooper shooting the rebel has to be constant - { - if (CheckForceSpawn(self, "shooter", "Stormtrooper")) return; - } - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm - { - SP_NPC_Stormtrooper(self); - return; - } - if (strcmp(lastKnownMap, "artus_topside") == 0) - { - if (self->behaviorSet[0]) // Check for NULL - { - if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners") == 0) - { - SP_NPC_Stormtrooper(self); - return; - } - if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners_crouch") == 0) - { - SP_NPC_Stormtrooper(self); - return; - } - } - - } SP_NPC_Spawn_Random(self); } else SP_NPC_Stormtrooper(self); @@ -3453,7 +3768,7 @@ void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaugh if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Ugnaught(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Ugnaught(self); } @@ -3462,22 +3777,6 @@ void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two TS thrower at the end of the mission - { - CheckForceSpawn(self, "t198", "Gran"); - return; - } - if (strcmp(lastKnownMap, "ns_starpad") == 0) - { - if (CheckForceSpawn(self, "back_squad1", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad2", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad3", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad4", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad1", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad2", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad3", "Gran")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad4", "Gran")) return; // For Lando in the hangar - } SP_NPC_Spawn_Random(self); } else SP_NPC_Gran(self); @@ -3487,25 +3786,6 @@ void SP_NPC_Rodian_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "ns_streets") == 0) - { - if (CheckForceSpawn(self, "bouncer_main1", "Rodian")) return; // The two Rodians that will get our weapons - if (CheckForceSpawn(self, "bouncer_main2", "Rodian")) return; // The two Rodians that will get our weapons - } - if (strcmp(lastKnownMap, "ns_starpad") == 0) - { - if (CheckForceSpawn(self, "reelo_thug", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "end_thug", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "bea", "Rodian")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "back_squad1", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad2", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad3", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad4", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad1", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad2", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad3", "Rodian")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad4", "Rodian")) return; // For Lando in the hangar - } SP_NPC_Spawn_Random(self); } else SP_NPC_Rodian(self); @@ -3515,24 +3795,6 @@ void SP_NPC_Weequay_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "ns_starpad") == 0) - { - if (CheckForceSpawn(self, "reelo_thug", "Weequay")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "end_thug", "Weequay")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "bea", "Weequay")) return; // The guys with Reelo at the end of the mission - if (CheckForceSpawn(self, "back_squad1", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad2", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad3", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "back_squad4", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad1", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad2", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad3", "Weequay")) return; // For Lando in the hangar - if (CheckForceSpawn(self, "front_squad4", "Weequay")) return; // For Lando in the hangar - } - if (strcmp(lastKnownMap, "ns_hideout") == 0) - { - if (CheckForceSpawn(self, "trap", "Weequay")) return; // The guys after the 5 turrets - } SP_NPC_Spawn_Random(self); } else SP_NPC_Weequay(self); @@ -3560,83 +3822,6 @@ void SP_NPC_Imperial_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - // Won't make a special function, he is an unique case - if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick has to be constant - { - if (self->behaviorSet[0]) // Check for NULL - { - if (strcmp(self->behaviorSet[0], "cairn_assembly/silent_stand") == 0) - { - SP_NPC_Imperial(self); - return; - } - } - } - if (strcmp(lastKnownMap, "kejim_base") == 0) - { - if (CheckForceSpawn(self, "explosion_victims", "Imperial")) return; // The dead Imperial holding a security key - if (CheckForceSpawn(self, "ambush_io", "Imperial")) return; // The first Imperial - if (self->behaviorSet[0] && (strcmp(self->behaviorSet[0], "common/crouchshoot") == 0)) - { - // ONLY the Imperial hiding in the corner, not the one standing (they both have the same target name) - CheckForceSpawn(self, "corridor_enemies", "Imperial"); - return; - } - } - if (strcmp(lastKnownMap, "artus_detention") == 0) - { - if (CheckForceSpawn(self, "warden", "Imperial")) return; // The warden that we have hostage - } - if (strcmp(lastKnownMap, "doom_detention") == 0) - { - if (CheckForceSpawn(self, "jailer", "Imperial")) return; // The jailer of Jan - if (self->message && strcmp(self->message, "ele_key2") == 0) // The Imperial holding a key in the big room - { - CheckForceSpawn(self, "squad7", "Imperial"); - return; - } - } - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm - { - SP_NPC_Imperial(self); - return; - } - if (strcmp(lastKnownMap, "artus_topside") == 0) - { - if (self->message && strcmp(self->message, "shield_key") == 0) // The Imperial holding a key in the ATST room - { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; - } - } - if (strcmp(lastKnownMap, "bespin_streets") == 0) - { - if (self->message && strcmp(self->message, "exit_key") == 0) // The Imperial holding a key at the end of the level - { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; - } - } - if (strcmp(lastKnownMap, "bespin_platform") == 0) - { - if (self->message && strcmp(self->message, "control_room") == 0) // The Imperial holding a key at the end of the level - { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; - } - } - if (strcmp(lastKnownMap, "doom_comm") == 0) - { - if (self->message && strcmp(self->message, "hey_presto") == 0) // The Imperial holding a key to access the 'call room' - { - // This guy doesn't have a target, so we just spawn him - SP_NPC_Imperial(self); - return; - } - } SP_NPC_Spawn_Random(self); } else SP_NPC_Imperial(self); @@ -3646,11 +3831,6 @@ void SP_NPC_ImpWorker_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, if a friendly NPC and an ennemy NPC starts to fight, they WILL trigger the alarm - { - SP_NPC_ImpWorker(self); - return; - } SP_NPC_Spawn_Random(self); } else SP_NPC_ImpWorker(self); @@ -3669,28 +3849,6 @@ void SP_NPC_Reborn_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "bespin_undercity") == 0) // Undercity, the two reborn at the end of the mission - { - CheckForceSpawn(self, "t179", "Reborn"); - CheckForceSpawn(self, "t199", "Reborn"); - return; - } - if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The two reborn we have to kill in oprder to spawn the ATST at the end - { - CheckForceSpawn(self, "squad18", "Reborn"); - return; - } - if (strcmp(lastKnownMap, "doom_detention") == 0) // The two reborn at the end to access the jailer - { - CheckForceSpawn(self, "squad22", "Reborn"); - return; - } - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The two reborn out of the 3 kills we have to do - { - CheckForceSpawn(self, "bridge_count", "Reborn"); - CheckForceSpawn(self, "squad5", "Reborn"); - return; - } SP_NPC_Spawn_Random(self); } else SP_NPC_Reborn(self); @@ -3700,17 +3858,6 @@ void SP_NPC_ShadowTrooper_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - if (strcmp(lastKnownMap, "cairn_dock1") == 0) // We want to keep this map clean, too many undefined behaviours - { - SP_NPC_ShadowTrooper(self); - return; - } - if (strcmp(lastKnownMap, "yavin_courtyard") == 0) // The two reborn out of the 3 kills we have to do - { - CheckForceSpawn(self, "bridge_count", "Shadowtrooper"); - CheckForceSpawn(self, "squad5", "Shadowtrooper"); - return; - } SP_NPC_Spawn_Random(self); } else SP_NPC_ShadowTrooper(self); @@ -3891,7 +4038,7 @@ void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Droid_R2D2(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Droid_R2D2(self); } @@ -3900,7 +4047,7 @@ void SP_NPC_Droid_R5D2_Random(gentity_t* self) // R5D2 should spawn as self if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Droid_R5D2(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Droid_R5D2(self); } @@ -3909,7 +4056,7 @@ void SP_NPC_Droid_Protocol_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Droid_Protocol(self); + SP_NPC_Spawn_Random(self); } else SP_NPC_Droid_Protocol(self); } diff --git a/code/game/Q3_Interface.cpp b/code/game/Q3_Interface.cpp index 14134d03..92b450c0 100644 --- a/code/game/Q3_Interface.cpp +++ b/code/game/Q3_Interface.cpp @@ -39,6 +39,7 @@ extern void InitMoverTrData( gentity_t *ent ); extern qboolean SpotWouldTelefrag2( gentity_t *mover, vec3_t dest ); extern cvar_t *g_sex; extern cvar_t *g_timescale; +extern vmCvar_t cg_enableRandomizer; extern void G_SetEnemy( gentity_t *self, gentity_t *enemy ); //extern void FX_BorgTeleport( vec3_t org ); static void Q3_SetWeapon (int entID, const char *wp_name); @@ -3341,7 +3342,8 @@ static void Q3_SetWeapon (int entID, const char *wp_name) if(wp == WP_NONE) {//no weapon self->client->ps.weapon = WP_NONE; - if ( self->weaponModel >= 0 ) + //For some reason we're trying to remove weapons that don't exist + if ( self->weaponModel >= 0 && self->ghoul2.size()>0 && self->weaponModel) { gi.G2API_RemoveGhoul2Model( self->ghoul2, self->weaponModel ); self->weaponModel = -1; @@ -6630,7 +6632,7 @@ static void Q3_Set( int taskID, int entID, const char *type_name, const char *da } else { - Q3_DebugPrint( WL_ERROR, "Q3_SetAnimUpper: %s does not have anim %s!\n", ent->targetname, (char *)data ); + Q3_DebugPrint(WL_ERROR, "Q3_SetAnimUpper: %s does not have anim %s!\n", ent->targetname, (char*)data); } if ( Q3_SetAnimLower( entID, (char *) data ) ) { @@ -6641,6 +6643,15 @@ static void Q3_Set( int taskID, int entID, const char *type_name, const char *da { Q3_DebugPrint( WL_ERROR, "Q3_SetAnimLower: %s does not have anim %s!\n", ent->targetname, (char *)data ); } + if (both == 0 && cg_enableRandomizer.integer) { + int instantTimer = 1; + Q3_TaskIDSet(ent, TID_ANIM_UPPER, taskID); + Q3_TaskIDSet(ent, TID_ANIM_LOWER, taskID); + Q3_TaskIDSet(ent, TID_ANIM_BOTH, taskID); + PM_SetTorsoAnimTimer(ent, &instantTimer, 0); + PM_SetLegsAnimTimer(ent, &instantTimer, 0); + return; + } if ( both >= 2 ) { Q3_TaskIDSet( ent, TID_ANIM_BOTH, taskID ); diff --git a/code/game/bg_pmove.cpp b/code/game/bg_pmove.cpp index 4ecd036c..2111f1c2 100644 --- a/code/game/bg_pmove.cpp +++ b/code/game/bg_pmove.cpp @@ -7267,6 +7267,12 @@ void PM_WeaponLightsaber(void) // Check for WEAPON ATTACK // ********************************************************* + //We don't have an enemy, don't try to attack + //How the fuck did that get into release? It's checked everywhere else + if (cg_enableRandomizer.integer && !pm->gent->enemy) { + return; + } + weapon = &cg_weapons[pm->ps->weapon]; if(!delayed_fire) diff --git a/code/game/bg_slidemove.cpp b/code/game/bg_slidemove.cpp index 0e5bb47d..df060316 100644 --- a/code/game/bg_slidemove.cpp +++ b/code/game/bg_slidemove.cpp @@ -5,6 +5,8 @@ #include "bg_public.h" #include "bg_local.h" +extern vmCvar_t cg_enableRandomizer; + extern qboolean PM_ClientImpact( int otherEntityNum, qboolean damageSelf ); /* @@ -90,6 +92,11 @@ qboolean PM_SlideMove( float gravMod ) { // calculate position we are trying to move to VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end ); + //safety check here + if (cg_enableRandomizer.integer && (_isnan(end[0]) || isnan(end[1]) || _isnan(end[2]))) { + continue; + } + // see if we can make it there pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemask, (EG2_Collision)0, 0); diff --git a/code/game/g_combat.cpp b/code/game/g_combat.cpp index b5b35b33..f3cf5bbc 100644 --- a/code/game/g_combat.cpp +++ b/code/game/g_combat.cpp @@ -3431,7 +3431,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int if ( self->NPC->tempGoal ) { - if ( self->client->NPC_class == CLASS_DESANN && !strcmp(level.mapname, "yavin_final") ) + if ( (self->client->NPC_class == CLASS_DESANN || + (cg_enableRandomizer.integer && self->script_targetname && !Q_stricmp("real_desann", self->script_targetname))) + && !strcmp(level.mapname, "yavin_final")) { // Randomizer if (cg_enableRandomizer.integer) diff --git a/code/game/g_main.cpp b/code/game/g_main.cpp index c224e7d6..0d9a8eef 100644 --- a/code/game/g_main.cpp +++ b/code/game/g_main.cpp @@ -479,6 +479,8 @@ void G_FindTeams( void ) { continue; if (e->flags & FL_TEAMSLAVE) continue; + if (e->spawnflags & SFB_CINEMATIC) //Ignore cinematic NPCs + continue; e->teammaster = e; c++; c2++; @@ -983,7 +985,7 @@ void G_RunThink (gentity_t *ent) { goto runicarus; } - + ent->nextthink = 0; if ( ent->e_ThinkFunc == thinkF_NULL ) // actually you don't need this if I check for it in the next function -slc { @@ -1293,7 +1295,7 @@ void G_RunFrame( int levelTime ) { continue; ent = &g_entities[i]; - + if ( ent->waypoint != WAYPOINT_NONE && ent->noWaypointTime < level.time ) { diff --git a/code/game/g_missile.cpp b/code/game/g_missile.cpp index 106a742a..406ad488 100644 --- a/code/game/g_missile.cpp +++ b/code/game/g_missile.cpp @@ -16,6 +16,7 @@ extern qboolean PM_SaberInIdle( int move ); extern qboolean PM_SaberInAttack( int move ); extern qboolean PM_SaberInTransitionAny( int move ); extern qboolean PM_SaberInSpecialAttack( int anim ); +extern vmCvar_t cg_enableRandomizer; //------------------------------------------------------------------------- #ifdef _IMMERSION @@ -577,6 +578,10 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace, int hitLoc=HL_NONE ) other = &g_entities[trace->entityNum]; if ( other == ent ) { + //Debug convenience, this doesn't change anything in FinalBuild but prevents popups when debugging + if (cg_enableRandomizer.integer) { + return; + } assert(0&&"missile hit itself!!!"); return; } diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 037f1fe2..0cadd12e 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -273,12 +273,30 @@ void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *psWeaponModel ) return; } // give us a sabre model - ent->weaponModel = gi.G2API_InitGhoul2Model(ent->ghoul2, weaponModel, G_ModelIndex( weaponModel ), NULL, NULL, 0, 0); + // As long as it exists that is + if (!cg_enableRandomizer.integer || weaponModel) { + ent->weaponModel = gi.G2API_InitGhoul2Model(ent->ghoul2, weaponModel, G_ModelIndex(weaponModel), NULL, NULL, 0, 0); + } if ( ent->weaponModel != -1 ) { - // attach it to the hand - gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], - ent->handRBolt, ent->playerModel); + if (cg_enableRandomizer.integer && ent->handRBolt < 0) { + // Only try to add the weapon if we have a slot to attach it to, otherwise return + if ( ent->playerModel + && &ent->ghoul2[ent->playerModel].mBltlist + && &ent->ghoul2[ent->playerModel].mBltlist[1] + && &ent->ghoul2[ent->playerModel].mBltlist[1].boneNumber) { + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], + 1, ent->playerModel); + } + else { + return; + } + } + else { + // attach it to the hand + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], + ent->handRBolt, ent->playerModel); + } // set up a bolt on the end so we can get where the sabre muzzle is - we can assume this is always bolt 0 gi.G2API_AddBolt(&ent->ghoul2[ent->weaponModel], "*flash"); //gi.G2API_SetLodBias( &ent->ghoul2[ent->weaponModel], 0 ); @@ -4875,6 +4893,11 @@ void WP_SaberStartMissileBlockCheck( gentity_t *self, usercmd_t *ucmd ) trace_t trace; vec3_t traceTo, entDir; + //I am one of the end guys on ns_starpad and have to be killed with a turret, so if I block the game is softlocked + if (cg_enableRandomizer.integer && !Q_stricmp(level.mapname, "ns_starpad") + && self->targetname && !Q_strncmp(self->targetname, "end_thug", 8)) { + return; + } if ( self->client->ps.weapon != WP_SABER ) { diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp index 067adc99..7187e383 100644 --- a/code/randomizer/RandomizerUtils.cpp +++ b/code/randomizer/RandomizerUtils.cpp @@ -18,6 +18,9 @@ extern vmCvar_t cg_setSeed; // To access the game extern game_import_t gi; +static std::map teamsByName; +static std::map teamsByClass; + static void AddCharArrayToInt(string seedString, int* value) { for (int i = 0; i < seedString.size(); i++) { @@ -69,6 +72,107 @@ void RandomizerUtils::RegenerateSeed() } } +void initialiseNameMap() { + teamsByName["NPC_Kyle"] = TEAM_PLAYER; + teamsByName["NPC_Lando"] = TEAM_PLAYER; + teamsByName["NPC_Jan"] = TEAM_PLAYER; + teamsByName["NPC_MonMothma"] = TEAM_PLAYER; + teamsByName["NPC_Tavion"] = TEAM_ENEMY; + teamsByName["NPC_Reelo"] = TEAM_ENEMY; + teamsByName["NPC_Galak"] = TEAM_ENEMY; + teamsByName["NPC_Desann"] = TEAM_ENEMY; + teamsByName["NPC_Bartender"] = TEAM_ENEMY; + teamsByName["NPC_MorganKatarn"] = TEAM_PLAYER; + teamsByName["NPC_Jedi"] = TEAM_PLAYER; + teamsByName["NPC_Prisoner"] = TEAM_PLAYER; + teamsByName["NPC_Rebel"] = TEAM_PLAYER; + teamsByName["NPC_Stormtrooper"] = TEAM_ENEMY; + teamsByName["NPC_StormtrooperOfficer"] = TEAM_ENEMY; + teamsByName["NPC_Tie_Pilot"] = TEAM_ENEMY; + teamsByName["NPC_Ugnaught"] = TEAM_ENEMY; + teamsByName["NPC_Gran"] = TEAM_ENEMY; + teamsByName["NPC_Rodian"] = TEAM_ENEMY; + teamsByName["NPC_Weequay"] = TEAM_ENEMY; + teamsByName["NPC_Trandoshan"] = TEAM_ENEMY; + teamsByName["NPC_Imperial"] = TEAM_ENEMY; + teamsByName["NPC_ImpWorker"] = TEAM_ENEMY; + teamsByName["NPC_BespinCop"] = TEAM_PLAYER; + teamsByName["NPC_Reborn"] = TEAM_ENEMY; + teamsByName["NPC_ShadowTrooper"] = TEAM_ENEMY; + teamsByName["NPC_MineMonster"] = TEAM_NEUTRAL; + teamsByName["NPC_Droid_Interrogator"] = TEAM_ENEMY; + teamsByName["NPC_Droid_Probe"] = TEAM_ENEMY; + teamsByName["NPC_Droid_Seeker"] = TEAM_PLAYER; + teamsByName["NPC_Droid_Remote"] = TEAM_ENEMY; + teamsByName["NPC_Droid_Sentry"] = TEAM_ENEMY; + teamsByName["NPC_Droid_Gonk"] = TEAM_NEUTRAL; + teamsByName["NPC_Droid_Mouse"] = TEAM_ENEMY; + teamsByName["NPC_Droid_R2D2"] = TEAM_PLAYER; + teamsByName["NPC_Droid_R5D2"] = TEAM_PLAYER; + teamsByName["NPC_Droid_Protocol"] = TEAM_PLAYER; + teamsByName["NPC_Galak_Mech"] = TEAM_ENEMY; + teamsByName["NPC_SwampTrooper"] = TEAM_ENEMY; +} + +void initialiseMapByClass() { + teamsByClass[CLASS_KYLE] = TEAM_PLAYER; + teamsByClass[CLASS_LANDO] = TEAM_PLAYER; + teamsByClass[CLASS_JAN] = TEAM_PLAYER; + teamsByClass[CLASS_MONMOTHA] = TEAM_PLAYER; + teamsByClass[CLASS_TAVION] = TEAM_ENEMY; + teamsByClass[CLASS_REELO] = TEAM_ENEMY; + teamsByClass[CLASS_GALAK] = TEAM_ENEMY; + teamsByClass[CLASS_DESANN] = TEAM_ENEMY; + teamsByClass[CLASS_BARTENDER] = TEAM_ENEMY; + teamsByClass[CLASS_MORGANKATARN] = TEAM_PLAYER; + teamsByClass[CLASS_JEDI] = TEAM_PLAYER; + teamsByClass[CLASS_PRISONER] = TEAM_PLAYER; + teamsByClass[CLASS_REBEL] = TEAM_PLAYER; + teamsByClass[CLASS_STORMTROOPER] = TEAM_ENEMY; + teamsByClass[CLASS_UGNAUGHT] = TEAM_ENEMY; + teamsByClass[CLASS_GRAN] = TEAM_ENEMY; + teamsByClass[CLASS_RODIAN] = TEAM_ENEMY; + teamsByClass[CLASS_WEEQUAY] = TEAM_ENEMY; + teamsByClass[CLASS_TRANDOSHAN] = TEAM_ENEMY; + teamsByClass[CLASS_IMPERIAL] = TEAM_ENEMY; + teamsByClass[CLASS_IMPWORKER] = TEAM_ENEMY; + teamsByClass[CLASS_BESPIN_COP] = TEAM_PLAYER; + teamsByClass[CLASS_REBORN] = TEAM_ENEMY; + teamsByClass[CLASS_SHADOWTROOPER] = TEAM_ENEMY; + teamsByClass[CLASS_MINEMONSTER] = TEAM_NEUTRAL; + teamsByClass[CLASS_INTERROGATOR] = TEAM_ENEMY; + teamsByClass[CLASS_PROBE] = TEAM_ENEMY; + teamsByClass[CLASS_SEEKER] = TEAM_PLAYER; + teamsByClass[CLASS_REMOTE] = TEAM_ENEMY; + teamsByClass[CLASS_SENTRY] = TEAM_ENEMY; + teamsByClass[CLASS_GONK] = TEAM_NEUTRAL; + teamsByClass[CLASS_MOUSE] = TEAM_ENEMY; + teamsByClass[CLASS_R2D2] = TEAM_PLAYER; + teamsByClass[CLASS_R5D2] = TEAM_PLAYER; + teamsByClass[CLASS_PROTOCOL] = TEAM_PLAYER; + teamsByClass[CLASS_SWAMPTROOPER] = TEAM_ENEMY; + teamsByClass[CLASS_GALAKMECH] = TEAM_ENEMY; + teamsByClass[CLASS_NONE] = TEAM_PLAYER; +} + +team_t RandomizerUtils::GetClassTeamByClassname(char *npcClassname) +{ + if (!teamsByName["NPC_Kyle"]) { + initialiseNameMap(); + } + team_t valFromMap = teamsByName[npcClassname]; + return !valFromMap ? TEAM_FREE : valFromMap; +} + +team_t RandomizerUtils::GetClassTeamByClass(class_t npcClass) +{ + if (!teamsByClass[CLASS_KYLE]) { + initialiseMapByClass(); + } + team_t valFromMap = teamsByClass[npcClass]; + return !valFromMap ? TEAM_FREE : valFromMap; +} + void RandomizerInfoCommandCatcher(int page) { // List of colors @@ -129,5 +233,4 @@ void RandomizerInfoCommandCatcher(int page) default: return; } - } \ No newline at end of file diff --git a/code/randomizer/RandomizerUtils.h b/code/randomizer/RandomizerUtils.h index 54899e3f..aedf73ee 100644 --- a/code/randomizer/RandomizerUtils.h +++ b/code/randomizer/RandomizerUtils.h @@ -9,5 +9,7 @@ class RandomizerUtils public: static void seedRandomizer(std::string seedString, std::string levelName); static void RegenerateSeed(); + static team_t GetClassTeamByClassname(char *npcType); + static team_t GetClassTeamByClass(class_t npcClass); }; From 47ebb26994b24c2fec580a6f7fef63f5c60b36e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Mon, 16 Dec 2024 20:35:39 +0100 Subject: [PATCH 41/62] Fix for Kyle that couldn't attack with a saber. --- code/game/bg_pmove.cpp | 9 +++++++-- code/game/wp_saber.cpp | 11 ++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/code/game/bg_pmove.cpp b/code/game/bg_pmove.cpp index 2111f1c2..95e8264b 100644 --- a/code/game/bg_pmove.cpp +++ b/code/game/bg_pmove.cpp @@ -7269,8 +7269,13 @@ void PM_WeaponLightsaber(void) //We don't have an enemy, don't try to attack //How the fuck did that get into release? It's checked everywhere else - if (cg_enableRandomizer.integer && !pm->gent->enemy) { - return; + if (cg_enableRandomizer.integer) + { + if (strcmp(pm->gent->classname, "player") == 0) // Fix : Kyle couldn't attack + { + // Nothing + } + else if (!pm->gent->enemy) return; } weapon = &cg_weapons[pm->ps->weapon]; diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 0cadd12e..8233ffdd 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -279,16 +279,21 @@ void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *psWeaponModel ) } if ( ent->weaponModel != -1 ) { - if (cg_enableRandomizer.integer && ent->handRBolt < 0) { + if (cg_enableRandomizer.integer && ent->handRBolt > 0) { // Only try to add the weapon if we have a slot to attach it to, otherwise return - if ( ent->playerModel + if (ent->playerModel && &ent->ghoul2[ent->playerModel].mBltlist && &ent->ghoul2[ent->playerModel].mBltlist[1] && &ent->ghoul2[ent->playerModel].mBltlist[1].boneNumber) { gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], 1, ent->playerModel); } - else { + else if (strcmp(ent->classname, "player") == 0) // Fix for Kyle as the player + { + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], ent->handRBolt, ent->playerModel); + } + else + { return; } } From c9a10d9e3a2d174780404540dbf834af40e0f044 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Mon, 16 Dec 2024 20:59:26 +0000 Subject: [PATCH 42/62] Refactor sabre model safety checks (#10) --- code/game/wp_saber.cpp | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 8233ffdd..bd9dfe30 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -272,39 +272,39 @@ void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *psWeaponModel ) { return; } - // give us a sabre model - // As long as it exists that is - if (!cg_enableRandomizer.integer || weaponModel) { - ent->weaponModel = gi.G2API_InitGhoul2Model(ent->ghoul2, weaponModel, G_ModelIndex(weaponModel), NULL, NULL, 0, 0); - } - if ( ent->weaponModel != -1 ) - { - if (cg_enableRandomizer.integer && ent->handRBolt > 0) { - // Only try to add the weapon if we have a slot to attach it to, otherwise return - if (ent->playerModel - && &ent->ghoul2[ent->playerModel].mBltlist - && &ent->ghoul2[ent->playerModel].mBltlist[1] - && &ent->ghoul2[ent->playerModel].mBltlist[1].boneNumber) { - gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], - 1, ent->playerModel); - } - else if (strcmp(ent->classname, "player") == 0) // Fix for Kyle as the player + // give us a sabre model + ent->weaponModel = gi.G2API_InitGhoul2Model(ent->ghoul2, weaponModel, G_ModelIndex(weaponModel), NULL, NULL, 0, 0); + + if (cg_enableRandomizer.integer && Q_stricmp(ent->classname, "player")) + {//Randomizer safe version + //We have a weapon and a model to attach it to + if (weaponModel && ent->playerModel != -1) + { + //We have a hand to bolt it to + if (ent->handRBolt != -1) { - gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], ent->handRBolt, ent->playerModel); + // attach it to the hand + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], + ent->handRBolt, ent->playerModel); } else { - return; + //If not just put it wherever lol + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], + 1, ent->playerModel); } + // set up a bolt on the end so we can get where the sabre muzzle is - we can assume this is always bolt 0 + gi.G2API_AddBolt(&ent->ghoul2[ent->weaponModel], "*flash"); } - else { - // attach it to the hand - gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], - ent->handRBolt, ent->playerModel); - } + } + else + {//Vanilla version & Kyle + // attach it to the hand + gi.G2API_AttachG2Model(&ent->ghoul2[ent->weaponModel], &ent->ghoul2[ent->playerModel], + ent->handRBolt, ent->playerModel); // set up a bolt on the end so we can get where the sabre muzzle is - we can assume this is always bolt 0 gi.G2API_AddBolt(&ent->ghoul2[ent->weaponModel], "*flash"); - //gi.G2API_SetLodBias( &ent->ghoul2[ent->weaponModel], 0 ); + //gi.G2API_SetLodBias( &ent->ghoul2[ent->weaponModel], 0 ); } } From 5c3815c454873cbc9e151ede60a57e0f86bd36c0 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Thu, 19 Dec 2024 20:57:15 +0000 Subject: [PATCH 43/62] Fix behaviour set assignment for droids, fix Interrogator not doing anything when no enemy present, add extra safety check for weapon model create (#11) --- code/game/AI_Interrogator.cpp | 6 +++++- code/game/NPC.cpp | 35 +++++++++++++++++++++++++++++++++++ code/game/wp_saber.cpp | 4 ++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/code/game/AI_Interrogator.cpp b/code/game/AI_Interrogator.cpp index 1751a36d..4085f112 100644 --- a/code/game/AI_Interrogator.cpp +++ b/code/game/AI_Interrogator.cpp @@ -8,6 +8,7 @@ void Interrogator_Idle( void ); void DeathFX( gentity_t *ent ); extern void G_SoundOnEnt( gentity_t *ent, soundChannel_t channel, const char *soundPath ); +extern vmCvar_t cg_enableRandomizer; enum { @@ -428,7 +429,10 @@ void Interrogator_Idle( void ) { G_SoundOnEnt( NPC, CHAN_AUTO, "sound/chars/mark1/misc/anger.wav" ); NPC_UpdateAngles( qtrue, qtrue ); - return; + if (!cg_enableRandomizer.integer) + { + return; + } } Interrogator_MaintainHeight(); diff --git a/code/game/NPC.cpp b/code/game/NPC.cpp index 097ed428..c6efb664 100644 --- a/code/game/NPC.cpp +++ b/code/game/NPC.cpp @@ -36,6 +36,7 @@ extern void NPC_CheckCharmed( void ); extern cvar_t *g_dismemberment; extern cvar_t *g_saberRealisticCombat; +extern vmCvar_t cg_enableRandomizer; //Local Variables // ai debug cvars @@ -1789,6 +1790,40 @@ void NPC_RunBehavior( int team, int bState ) break; default: + if (cg_enableRandomizer.integer) + { + //For some reason a lot of droid behaviours are triggered by team so just copy them here if they're missed + switch (NPC->client->NPC_class) + { + case CLASS_PROBE: + NPC_BehaviorSet_ImperialProbe(bState); + return; + case CLASS_REMOTE: + NPC_BehaviorSet_Remote(bState); + return; + case CLASS_SENTRY: + NPC_BehaviorSet_Sentry(bState); + return; + case CLASS_INTERROGATOR: + NPC_BehaviorSet_Interrogator(bState); + return; + case CLASS_MINEMONSTER: + NPC_BehaviorSet_MineMonster(bState); + return; + case CLASS_HOWLER: + NPC_BehaviorSet_Howler(bState); + return; + case CLASS_MARK1: + NPC_BehaviorSet_Mark1(bState); + return; + case CLASS_MARK2: + NPC_BehaviorSet_Mark2(bState); + return; + case CLASS_GALAKMECH: + NPC_BSGM_Default(); + return; + } + } if ( NPC->client->NPC_class == CLASS_SEEKER ) { NPC_BehaviorSet_Seeker(bState); diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index bd9dfe30..6035f3cc 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -277,8 +277,8 @@ void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *psWeaponModel ) if (cg_enableRandomizer.integer && Q_stricmp(ent->classname, "player")) {//Randomizer safe version - //We have a weapon and a model to attach it to - if (weaponModel && ent->playerModel != -1) + //We have a weapon and a model to attach it to and a bolt point on the model + if (weaponModel && ent->playerModel != -1 && ent->ghoul2[ent->playerModel].mBltlist.size() > 0) { //We have a hand to bolt it to if (ent->handRBolt != -1) From 7657be64b72f259bd171e6c1a9fffdd35c1ad128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Wed, 25 Dec 2024 12:03:26 +0100 Subject: [PATCH 44/62] Making randomized secutiry keys usable, can be transfered between levels. (#13) --- code/game/g_inventory.cpp | 164 ++++++++++++++++++++++++++++++-------- 1 file changed, 129 insertions(+), 35 deletions(-) diff --git a/code/game/g_inventory.cpp b/code/game/g_inventory.cpp index d5e4c5b0..dfcffd60 100644 --- a/code/game/g_inventory.cpp +++ b/code/game/g_inventory.cpp @@ -5,6 +5,9 @@ #include "g_local.h" +// Randomizer +extern vmCvar_t cg_enableRandomizer; + /* ================ Goodie Keys @@ -62,18 +65,54 @@ Security Keys */ qboolean INV_SecurityKeyGive( gentity_t *target, const char *keyname ) { - if ( target == NULL || keyname == NULL || target->client == NULL ) + if (!cg_enableRandomizer.integer) { + if (target == NULL || keyname == NULL || target->client == NULL) + { + return qfalse; + } + + for (int i = 0; i <= 4; i++) + { + if (target->client->ps.security_key_message[i][0] == NULL) + {//fill in the first empty slot we find with this key + target->client->ps.inventory[INV_SECURITY_KEY]++; // He got the key + Q_strncpyz(target->client->ps.security_key_message[i], keyname, MAX_SECURITY_KEY_MESSSAGE, qtrue); + return qtrue; + } + } + //couldn't find an empty slot return qfalse; } - - for ( int i = 0; i <= 4; i++ ) + else // Randomizer, make a random taken key universally usable { - if ( target->client->ps.security_key_message[i][0] == NULL ) - {//fill in the first empty slot we find with this key - target->client->ps.inventory[INV_SECURITY_KEY]++; // He got the key - Q_strncpyz( target->client->ps.security_key_message[i], keyname, MAX_SECURITY_KEY_MESSSAGE, qtrue ); - return qtrue; + if (keyname != NULL) // Normal key, normal behavior + { + for (int i = 0; i <= 4; i++) + { + if (target->client->ps.security_key_message[i][0] == NULL) + {//fill in the first empty slot we find with this key + target->client->ps.inventory[INV_SECURITY_KEY]++; // He got the key + Q_strncpyz(target->client->ps.security_key_message[i], keyname, MAX_SECURITY_KEY_MESSSAGE, qtrue); + return qtrue; + } + } + //couldn't find an empty slot + return qfalse; + } + else // Randomly spawned key + { + for (int i = 0; i <= 4; i++) + { + if (target->client->ps.security_key_message[i][0] == NULL) + {//fill in the first empty slot we find with this key + target->client->ps.inventory[INV_SECURITY_KEY]++; // He got the key + Q_strncpyz(target->client->ps.security_key_message[i], "rando_key", MAX_SECURITY_KEY_MESSSAGE, qtrue); + return qtrue; + } + } + //couldn't find an empty slot + return qfalse; } } //couldn't find an empty slot @@ -82,56 +121,111 @@ qboolean INV_SecurityKeyGive( gentity_t *target, const char *keyname ) void INV_SecurityKeyTake( gentity_t *target, char *keyname ) { - if ( !target || !keyname || !target->client ) + if (!cg_enableRandomizer.integer) { - return; + if (!target || !keyname || !target->client) + { + return; + } + for (int i = 0; i <= 4; i++) + { + if (target->client->ps.security_key_message[i]) + { + if (!Q_stricmp(keyname, target->client->ps.security_key_message[i])) + { + target->client->ps.inventory[INV_SECURITY_KEY]--; // Take the key + target->client->ps.security_key_message[i][0] = NULL; + return; + } + } + /* + //don't do this because we could have removed one that's between 2 valid ones + else + { + break; + } + */ + } } - - for ( int i = 0; i <= 4; i++ ) + else // Randomizer, make a random taken key universally usable { - if ( target->client->ps.security_key_message[i] ) + for (int i = 0; i <= 4; i++) // Check for normal key first { - if ( !Q_stricmp( keyname, target->client->ps.security_key_message[i] ) ) + if (target->client->ps.security_key_message[i]) { - target->client->ps.inventory[INV_SECURITY_KEY]--; // Take the key - target->client->ps.security_key_message[i][0] = NULL; - return; + if (!Q_stricmp(keyname, target->client->ps.security_key_message[i])) + { + target->client->ps.inventory[INV_SECURITY_KEY]--; // Take the key + target->client->ps.security_key_message[i][0] = NULL; + return; + } } } - /* - //don't do this because we could have removed one that's between 2 valid ones - else + for (int i = 0; i <= 4; i++) // Check for rando_key { - break; + if (target->client->ps.security_key_message[i]) + { + if (!Q_stricmp("rando_key", target->client->ps.security_key_message[i])) + { + target->client->ps.inventory[INV_SECURITY_KEY]--; // Take the key + target->client->ps.security_key_message[i][0] = NULL; + return; + } + } } - */ } + } qboolean INV_SecurityKeyCheck( gentity_t *target, char *keyname ) { - if ( !target || !keyname || !target->client ) + if (!cg_enableRandomizer.integer) { - return (qfalse); + if (!target || !keyname || !target->client) + { + return (qfalse); + } + for (int i = 0; i <= 4; i++) + { + if (target->client->ps.inventory[INV_SECURITY_KEY] && target->client->ps.security_key_message[i]) + { + if (!Q_stricmp(keyname, target->client->ps.security_key_message[i])) + { + return (qtrue); + } + } + /* + //don't do this because we could have removed one that's between 2 valid ones + else + { + break; + } + */ + } } - - for ( int i = 0; i <= 4; i++ ) + else // Randomizer, make a random taken key universally usable { - if ( target->client->ps.inventory[INV_SECURITY_KEY] && target->client->ps.security_key_message[i] ) + for (int i = 0; i <= 4; i++) // Check for normal key first { - if ( !Q_stricmp( keyname, target->client->ps.security_key_message[i] ) ) + if (target->client->ps.inventory[INV_SECURITY_KEY] && target->client->ps.security_key_message[i]) { - return (qtrue); + if (!Q_stricmp(keyname, target->client->ps.security_key_message[i])) + { + return (qtrue); + } } } - /* - //don't do this because we could have removed one that's between 2 valid ones - else + for (int i = 0; i <= 4; i++) // Check for rando_key { - break; + if (target->client->ps.inventory[INV_SECURITY_KEY] && target->client->ps.security_key_message[i]) + { + if (!Q_stricmp("rando_key", target->client->ps.security_key_message[i])) + { + return (qtrue); + } + } } - */ - } + } return (qfalse); } From 0055cbbc8811ed7d26abb217920d4d75c22fa1c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Wed, 25 Dec 2024 12:03:42 +0100 Subject: [PATCH 45/62] Added a randomized saber lenght (#12) --- code/game/wp_saber.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 6035f3cc..17186212 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -464,7 +464,6 @@ void WP_SaberInitBladeData( gentity_t *ent ) if (cg_enableRandomizer.integer) // Random saber style at pickup, but I need to NOT call rand() to keep NPC spawn consistent. { ent->client->ps.saberAnimLevel = (level.framenum + level.time) % 3 + 1; - int i = 0; } else // Normal gameplay (and yes, there is a glitch to get fast style in trial) { @@ -481,14 +480,35 @@ void WP_SaberInitBladeData( gentity_t *ent ) if ( ent->client->NPC_class == CLASS_DESANN ) {//longer saber ent->client->ps.saberLengthMax = 48; + if (cg_enableRandomizer.integer) // Would be the funniest thing ever, range of 25% to 400% of initial value + { + ent->client->ps.saberLengthMax = rand() % 181 + 12; + } } else if ( ent->client->NPC_class == CLASS_REBORN ) {//shorter saber ent->client->ps.saberLengthMax = 32; + if (cg_enableRandomizer.integer) // Would be the funniest thing ever, range of 25% to 400% of initial value + { + ent->client->ps.saberLengthMax = rand() % 121 + 8; + } } else {//standard saber length - ent->client->ps.saberLengthMax = 40; + ent->client->ps.saberLengthMax = 40; // Default + if (cg_enableRandomizer.integer) // Would be the funniest thing ever, range of 25% to 400% of initial value + { + if (ent->client->NPC_class != CLASS_KYLE) // Since it's at map load, and all npc are generated here, we may use rand() + { + ent->client->ps.saberLengthMax = rand() % 151 + 10; + } + else // That's Kyle, when he's getting the saber at trial or before, might as well use the current time like for the saber style (to be sonsistent with our seed) + { + // That's a range of 25% to 400% + ent->client->ps.saberLengthMax = (level.framenum + level.time) % 151 + 10; + } + + } } if ( ent->client->ps.saberEntityNum <= 0 || ent->client->ps.saberEntityNum >= ENTITYNUM_WORLD ) From 3c0f34018828ad5a641d8704e6b1aede53d7c029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Mon, 6 Jan 2025 19:28:47 +0100 Subject: [PATCH 46/62] Added some fixes to the list of bug found the 28 December (#14) * Added some fixes to the list of bug found the 28 December * Fixed multiple points : - Mine monsters replacers are now working properly (they have AI, and respect the scripts during the guardian sequence) - Fixed the Tavion cutscene, where NPC could die if they didn't have enough HP nor force powers (death by fall) - Reduced the bonus hitbox if items to make the elevator on ns_hideout work (collision problem with the items in the secret zone) * Temp fix for the warden in artus_detention. * The rest of the modifications to fix all softlocks. * Fixed crash (some NPCs don't have targetname, making a write error) + removing randomized first weapon. * Add a new version number --- code/game/NPC_spawn.cpp | 259 ++++++++++++++++++++++++++-- code/game/bg_pmove.cpp | 7 + code/game/g_client.cpp | 4 +- code/game/g_items.cpp | 12 +- code/game/wp_saber.cpp | 6 +- code/randomizer/RandomizerUtils.cpp | 6 +- code/win32/AutoVersion.h | 6 +- 7 files changed, 271 insertions(+), 29 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 81e034fa..98022e49 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -3609,7 +3609,103 @@ void SP_NPC_Spawn_Random(gentity_t* self) } } -// If the Randomizer is disabled, just a bit of process time is added at every check, but at least it should be comptable with the standard SpeedOutcast +// Used for Lando, Jan, and other NPCs that have to be humanoid due to their size (door in artus_detention is too small for Desann for example) +void SP_NPC_Spawn_Random_Humanoid(gentity_t* self) +{ + int numberOfHumanoid = 25; + int rng = rand() % numberOfHumanoid; + + // Amber found a way to have any kind of NPC. + if (tabSize == 50) + { + for (int i = 0; i < tabSize; i++) tabLockedInNPC[i] = i; + } + + switch (rng) + { + case 0: + SP_NPC_Lando(self); + break; + case 1: + SP_NPC_Jan(self); + break; + case 2: + SP_NPC_Luke(self); + break; + case 3: + SP_NPC_MonMothma(self); + break; + case 4: + SP_NPC_Tavion(self); + break; + case 5: + SP_NPC_Reelo(self); + break; + case 6: + SP_NPC_Bartender(self); + break; + case 7: + SP_NPC_MorganKatarn(self); + break; + case 8: + SP_NPC_Jedi(self); + break; + case 9: + SP_NPC_Prisoner(self); + break; + case 10: + SP_NPC_Rebel(self); + break; + case 11: + SP_NPC_Stormtrooper(self); + break; + case 12: + SP_NPC_StormtrooperOfficer(self); + break; + case 13: + SP_NPC_Tie_Pilot(self); + break; + case 14: + SP_NPC_Ugnaught(self); + break; + case 15: + SP_NPC_Gran(self); + break; + case 16: + SP_NPC_Rodian(self); + break; + case 17: + SP_NPC_Weequay(self); + break; + case 18: + SP_NPC_Trandoshan(self); + break; + case 19: + SP_NPC_SwampTrooper(self); + break; + case 20: + SP_NPC_Imperial(self); + break; + case 21: + SP_NPC_ImpWorker(self); + break; + case 22: + SP_NPC_BespinCop(self); + break; + case 23: + SP_NPC_Reborn(self); + break; + case 24: + SP_NPC_ShadowTrooper(self); + break; + default: // Secours + SP_NPC_Stormtrooper(self); + //SP_NPC_Spawn_Random(self); + break; + } +} + +// If the Randomizer is disabled, just a bit of process time is added at every check, but at least it should be comptable with the standard SpeedOutcast since time is paused during load void SP_NPC_Kyle_Random(gentity_t* self) // Kyle should always spawn as Kyle { if (cg_enableRandomizer.integer) @@ -3624,7 +3720,9 @@ void SP_NPC_Lando_Random(gentity_t* self) // Lando should always spawn as Lando if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + //SP_NPC_Lando(self); + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_Lando(self); } @@ -3633,7 +3731,8 @@ void SP_NPC_Jan_Random(gentity_t* self) // Jan should always spawn as Jan if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_Jan(self); } @@ -3642,7 +3741,8 @@ void SP_NPC_Luke_Random(gentity_t* self) // Luke should always spawn as Luke if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_Luke(self); } @@ -3651,7 +3751,8 @@ void SP_NPC_MonMothma_Random(gentity_t* self) // MonMothma should always spawn a if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_MonMothma(self); } @@ -3661,6 +3762,7 @@ void SP_NPC_Tavion_Random(gentity_t* self) // Tavion should always spawn as Tavi { CheckIfMapChanged(); SP_NPC_Spawn_Random(self); + //SP_NPC_Tavion(self); } else SP_NPC_Tavion(self); } @@ -3669,7 +3771,8 @@ void SP_NPC_Reelo_Random(gentity_t* self) // Reelo should always spawn as Reelo if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_Reelo(self); } @@ -3687,7 +3790,8 @@ void SP_NPC_Desann_Random(gentity_t* self) // Desann should always spawn as Desa if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Spawn_Random_Humanoid(self); // As a droid, the cutscene before the final 'fight' might be infinite } else SP_NPC_Desann(self); } @@ -3741,6 +3845,23 @@ void SP_NPC_Stormtrooper_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); + // In case of "normal" gameplay ie not doing the turret skip, you need to be able to kill them (and not get stuck in doors) + if (strcmp(lastKnownMap, "artus_topside") == 0) + { + if (self->behaviorSet[0]) // Check for NULL + { + if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners") == 0) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + if (strcmp(self->behaviorSet[0], "artus_topside/shoot_prisoners_crouch") == 0) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } + } SP_NPC_Spawn_Random(self); } else SP_NPC_Stormtrooper(self); @@ -3768,7 +3889,9 @@ void SP_NPC_Ugnaught_Random(gentity_t* self) // Ugnaught should spawn as Ugnaugh if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + // For size, they may not hit triggers otherwise + SP_NPC_Spawn_Random_Humanoid(self); } else SP_NPC_Ugnaught(self); } @@ -3777,6 +3900,29 @@ void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys if (cg_enableRandomizer.integer) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->NPC_targetname, "back_squad1") + || !strcmp(self->NPC_targetname, "back_squad2") + || !strcmp(self->NPC_targetname, "back_squad3") + || !strcmp(self->NPC_targetname, "back_squad4") + || !strcmp(self->NPC_targetname, "front_squad1") + || !strcmp(self->NPC_targetname, "front_squad2") + || !strcmp(self->NPC_targetname, "front_squad3") + || !strcmp(self->NPC_targetname, "front_squad4")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } SP_NPC_Spawn_Random(self); } else SP_NPC_Gran(self); @@ -3786,6 +3932,35 @@ void SP_NPC_Rodian_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->NPC_targetname, "back_squad1") + || !strcmp(self->NPC_targetname, "back_squad2") + || !strcmp(self->NPC_targetname, "back_squad3") + || !strcmp(self->NPC_targetname, "back_squad4") + || !strcmp(self->NPC_targetname, "front_squad1") + || !strcmp(self->NPC_targetname, "front_squad2") + || !strcmp(self->NPC_targetname, "front_squad3") + || !strcmp(self->NPC_targetname, "front_squad4") + || !strcmp(self->targetname, "reelo_thug") + || !strcmp(self->targetname, "end_thug") + || !strcmp(self->targetname, "bea") + || !strcmp(self->NPC_targetname, "reelo_thug") + || !strcmp(self->NPC_targetname, "end_thug") + || !strcmp(self->NPC_targetname, "bea")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } SP_NPC_Spawn_Random(self); } else SP_NPC_Rodian(self); @@ -3795,6 +3970,35 @@ void SP_NPC_Weequay_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "ns_starpad") == 0) + { + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->NPC_targetname, "back_squad1") + || !strcmp(self->NPC_targetname, "back_squad2") + || !strcmp(self->NPC_targetname, "back_squad3") + || !strcmp(self->NPC_targetname, "back_squad4") + || !strcmp(self->NPC_targetname, "front_squad1") + || !strcmp(self->NPC_targetname, "front_squad2") + || !strcmp(self->NPC_targetname, "front_squad3") + || !strcmp(self->NPC_targetname, "front_squad4") + || !strcmp(self->targetname, "reelo_thug") + || !strcmp(self->targetname, "end_thug") + || !strcmp(self->targetname, "bea") + || !strcmp(self->NPC_targetname, "reelo_thug") + || !strcmp(self->NPC_targetname, "end_thug") + || !strcmp(self->NPC_targetname, "bea")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } SP_NPC_Spawn_Random(self); } else SP_NPC_Weequay(self); @@ -3822,6 +4026,33 @@ void SP_NPC_Imperial_Random(gentity_t* self) if (cg_enableRandomizer.integer) { CheckIfMapChanged(); + if (strcmp(lastKnownMap, "artus_detention") == 0) // The warden that we have hostage + { + if (!strcmp(self->targetname, "warden") || !strcmp(self->NPC_targetname, "warden")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } + if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick + { + if (self->behaviorSet[0]) // Check for NULL + { + if (strcmp(self->behaviorSet[0], "cairn_assembly/silent_stand") == 0) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } + } + if (strcmp(lastKnownMap, "doom_detention") == 0) // The jailer of Jan + { + if (!strcmp(self->targetname, "jailer") || !strcmp(self->NPC_targetname, "jailer")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } + } SP_NPC_Spawn_Random(self); } else SP_NPC_Imperial(self); @@ -4024,7 +4255,7 @@ void SP_NPC_Droid_Gonk_Random(gentity_t* self) } else SP_NPC_Droid_Gonk(self); } -void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse +void SP_NPC_Droid_Mouse_Random(gentity_t* self) // Mouse should spawn as Mouse because of size in kejim { if (cg_enableRandomizer.integer) { @@ -4042,12 +4273,13 @@ void SP_NPC_Droid_R2D2_Random(gentity_t* self) // R2D2 should spawn as self } else SP_NPC_Droid_R2D2(self); } -void SP_NPC_Droid_R5D2_Random(gentity_t* self) // R5D2 should spawn as self +void SP_NPC_Droid_R5D2_Random(gentity_t* self) // R5D2 should spawn as self, because of size in bespin { if (cg_enableRandomizer.integer) { CheckIfMapChanged(); - SP_NPC_Spawn_Random(self); + //SP_NPC_Spawn_Random(self); + SP_NPC_Droid_R5D2(self); } else SP_NPC_Droid_R5D2(self); } @@ -4065,11 +4297,6 @@ void SP_NPC_Droid_Protocol_Random(gentity_t* self) - - - - - //NPC console commands /* NPC_Spawn_f diff --git a/code/game/bg_pmove.cpp b/code/game/bg_pmove.cpp index 95e8264b..52f43e91 100644 --- a/code/game/bg_pmove.cpp +++ b/code/game/bg_pmove.cpp @@ -2191,6 +2191,13 @@ static void PM_CrashLandDamage( int damage ) { if ( pm->gent->NPC && pm->gent->NPC->aiFlags & NPCAI_DIE_ON_IMPACT ) { + if (cg_enableRandomizer.integer) + { + if (pm->gent->targetname) + { + if (!strcmp(pm->gent->targetname, "cinematic23_tavion")) return; // Please don't die MR NPC replacing Tavion + } + } damage = 1000; } else diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index d9028d8c..ab154631 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -1605,7 +1605,9 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded // Posto : Hey, we can randomize our first weapon ! if (cg_enableRandomizer.integer) { - client->ps.stats[STAT_WEAPONS] |= (1 << (weapon_t)(GetRandomizedWeapon())); + // Inconsistent seed with that + // client->ps.stats[STAT_WEAPONS] |= (1 << (weapon_t)(GetRandomizedWeapon())); + client->ps.stats[STAT_WEAPONS] |= (1 << WP_BRYAR_PISTOL); //these are precached in g_items, ClearRegisteredItems() } else { diff --git a/code/game/g_items.cpp b/code/game/g_items.cpp index 51e866f7..c1b7d9e1 100644 --- a/code/game/g_items.cpp +++ b/code/game/g_items.cpp @@ -809,12 +809,12 @@ void Use_Item( gentity_t *ent, gentity_t *other, gentity_t *activator ) //====================================================================== void updateItemMinsMaxs(gitem_t *item) { - item->mins[0] = item->mins[0] * 1.5; - item->mins[1] = item->mins[1] * 1.5; - item->mins[2] = item->mins[2] * 1.5; - item->maxs[0] = item->maxs[0] * 1.5; - item->maxs[1] = item->maxs[1] * 1.5; - item->maxs[2] = item->maxs[2] * 1.5; + item->mins[0] = item->mins[0] * 1.2; + item->mins[1] = item->mins[1] * 1.2; + item->mins[2] = item->mins[2] * 1.2; + item->maxs[0] = item->maxs[0] * 1.2; + item->maxs[1] = item->maxs[1] * 1.2; + item->maxs[2] = item->maxs[2] * 1.2; } /* diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 17186212..ac1e0e1f 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -4920,7 +4920,11 @@ void WP_SaberStartMissileBlockCheck( gentity_t *self, usercmd_t *ucmd ) //I am one of the end guys on ns_starpad and have to be killed with a turret, so if I block the game is softlocked if (cg_enableRandomizer.integer && !Q_stricmp(level.mapname, "ns_starpad") - && self->targetname && !Q_strncmp(self->targetname, "end_thug", 8)) { + && self->targetname && !Q_strncmp(self->targetname, "end_thug", 8) + || cg_enableRandomizer.integer && !Q_stricmp(level.mapname, "ns_starpad") + && self->targetname && !Q_strncmp(self->targetname, "reelo_thug", 10) + || cg_enableRandomizer.integer && !Q_stricmp(level.mapname, "ns_starpad") + && self->targetname && !Q_strncmp(self->targetname, "bea", 3)) { return; } diff --git a/code/randomizer/RandomizerUtils.cpp b/code/randomizer/RandomizerUtils.cpp index 7187e383..dbd189de 100644 --- a/code/randomizer/RandomizerUtils.cpp +++ b/code/randomizer/RandomizerUtils.cpp @@ -99,7 +99,8 @@ void initialiseNameMap() { teamsByName["NPC_BespinCop"] = TEAM_PLAYER; teamsByName["NPC_Reborn"] = TEAM_ENEMY; teamsByName["NPC_ShadowTrooper"] = TEAM_ENEMY; - teamsByName["NPC_MineMonster"] = TEAM_NEUTRAL; + //teamsByName["NPC_MineMonster"] = TEAM_NEUTRAL; + teamsByName["NPC_MineMonster"] = TEAM_ENEMY; teamsByName["NPC_Droid_Interrogator"] = TEAM_ENEMY; teamsByName["NPC_Droid_Probe"] = TEAM_ENEMY; teamsByName["NPC_Droid_Seeker"] = TEAM_PLAYER; @@ -139,7 +140,8 @@ void initialiseMapByClass() { teamsByClass[CLASS_BESPIN_COP] = TEAM_PLAYER; teamsByClass[CLASS_REBORN] = TEAM_ENEMY; teamsByClass[CLASS_SHADOWTROOPER] = TEAM_ENEMY; - teamsByClass[CLASS_MINEMONSTER] = TEAM_NEUTRAL; + //teamsByClass[CLASS_MINEMONSTER] = TEAM_NEUTRAL; + teamsByClass[CLASS_MINEMONSTER] = TEAM_ENEMY; teamsByClass[CLASS_INTERROGATOR] = TEAM_ENEMY; teamsByClass[CLASS_PROBE] = TEAM_ENEMY; teamsByClass[CLASS_SEEKER] = TEAM_PLAYER; diff --git a/code/win32/AutoVersion.h b/code/win32/AutoVersion.h index 4569e3dd..b628beca 100644 --- a/code/win32/AutoVersion.h +++ b/code/win32/AutoVersion.h @@ -2,11 +2,11 @@ #define __AUTO_VERSION_HEADER #define VERSION_MAJOR_RELEASE 1 -#define VERSION_MINOR_RELEASE 0 +#define VERSION_MINOR_RELEASE 1 #define VERSION_EXTERNAL_BUILD 0 #define VERSION_INTERNAL_BUILD 0 -#define VERSION_STRING "1, 0, 0, 0" -#define VERSION_STRING_DOTTED "1.0.0.0" +#define VERSION_STRING "1, 1, 0, 0" +#define VERSION_STRING_DOTTED "1.1.0.0" #endif // __AUTO_VERSION_HEADER From 5828bdca91a601252faf9c203a0c7d2d5cb6d4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Mon, 6 Jan 2025 20:18:03 +0100 Subject: [PATCH 47/62] Secured read on artus_detention warden, preventing crashes. --- code/game/NPC_spawn.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 98022e49..86bb014b 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -4028,10 +4028,13 @@ void SP_NPC_Imperial_Random(gentity_t* self) CheckIfMapChanged(); if (strcmp(lastKnownMap, "artus_detention") == 0) // The warden that we have hostage { - if (!strcmp(self->targetname, "warden") || !strcmp(self->NPC_targetname, "warden")) + if (self->targetname) { - SP_NPC_Spawn_Random_Humanoid(self); - return; + if (!strcmp(self->targetname, "warden")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } } } if (strcmp(lastKnownMap, "cairn_assembly") == 0) // The officer we have to mindtrick From b7749fd932d526cc95bd993cd2fbf1ec568dacf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Mon, 6 Jan 2025 22:00:41 +0100 Subject: [PATCH 48/62] Safe read on variables, the last one I hope. --- code/game/NPC_spawn.cpp | 123 ++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 69 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 86bb014b..2a2c92e4 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -3902,25 +3902,23 @@ void SP_NPC_Gran_Random(gentity_t* self) // Who is that ? It's the TD guys CheckIfMapChanged(); if (strcmp(lastKnownMap, "ns_starpad") == 0) { - if (!strcmp(self->targetname, "back_squad1") - || !strcmp(self->targetname, "back_squad2") - || !strcmp(self->targetname, "back_squad3") - || !strcmp(self->targetname, "back_squad4") - || !strcmp(self->targetname, "front_squad1") - || !strcmp(self->targetname, "front_squad2") - || !strcmp(self->targetname, "front_squad3") - || !strcmp(self->targetname, "front_squad4") - || !strcmp(self->NPC_targetname, "back_squad1") - || !strcmp(self->NPC_targetname, "back_squad2") - || !strcmp(self->NPC_targetname, "back_squad3") - || !strcmp(self->NPC_targetname, "back_squad4") - || !strcmp(self->NPC_targetname, "front_squad1") - || !strcmp(self->NPC_targetname, "front_squad2") - || !strcmp(self->NPC_targetname, "front_squad3") - || !strcmp(self->NPC_targetname, "front_squad4")) + if (self->targetname) { - SP_NPC_Spawn_Random_Humanoid(self); - return; + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->targetname, "reelo_thug") + || !strcmp(self->targetname, "end_thug") + || !strcmp(self->targetname, "bea")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } } } SP_NPC_Spawn_Random(self); @@ -3934,31 +3932,23 @@ void SP_NPC_Rodian_Random(gentity_t* self) CheckIfMapChanged(); if (strcmp(lastKnownMap, "ns_starpad") == 0) { - if (!strcmp(self->targetname, "back_squad1") - || !strcmp(self->targetname, "back_squad2") - || !strcmp(self->targetname, "back_squad3") - || !strcmp(self->targetname, "back_squad4") - || !strcmp(self->targetname, "front_squad1") - || !strcmp(self->targetname, "front_squad2") - || !strcmp(self->targetname, "front_squad3") - || !strcmp(self->targetname, "front_squad4") - || !strcmp(self->NPC_targetname, "back_squad1") - || !strcmp(self->NPC_targetname, "back_squad2") - || !strcmp(self->NPC_targetname, "back_squad3") - || !strcmp(self->NPC_targetname, "back_squad4") - || !strcmp(self->NPC_targetname, "front_squad1") - || !strcmp(self->NPC_targetname, "front_squad2") - || !strcmp(self->NPC_targetname, "front_squad3") - || !strcmp(self->NPC_targetname, "front_squad4") - || !strcmp(self->targetname, "reelo_thug") - || !strcmp(self->targetname, "end_thug") - || !strcmp(self->targetname, "bea") - || !strcmp(self->NPC_targetname, "reelo_thug") - || !strcmp(self->NPC_targetname, "end_thug") - || !strcmp(self->NPC_targetname, "bea")) + if (self->targetname) { - SP_NPC_Spawn_Random_Humanoid(self); - return; + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->targetname, "reelo_thug") + || !strcmp(self->targetname, "end_thug") + || !strcmp(self->targetname, "bea")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } } } SP_NPC_Spawn_Random(self); @@ -3972,31 +3962,23 @@ void SP_NPC_Weequay_Random(gentity_t* self) CheckIfMapChanged(); if (strcmp(lastKnownMap, "ns_starpad") == 0) { - if (!strcmp(self->targetname, "back_squad1") - || !strcmp(self->targetname, "back_squad2") - || !strcmp(self->targetname, "back_squad3") - || !strcmp(self->targetname, "back_squad4") - || !strcmp(self->targetname, "front_squad1") - || !strcmp(self->targetname, "front_squad2") - || !strcmp(self->targetname, "front_squad3") - || !strcmp(self->targetname, "front_squad4") - || !strcmp(self->NPC_targetname, "back_squad1") - || !strcmp(self->NPC_targetname, "back_squad2") - || !strcmp(self->NPC_targetname, "back_squad3") - || !strcmp(self->NPC_targetname, "back_squad4") - || !strcmp(self->NPC_targetname, "front_squad1") - || !strcmp(self->NPC_targetname, "front_squad2") - || !strcmp(self->NPC_targetname, "front_squad3") - || !strcmp(self->NPC_targetname, "front_squad4") - || !strcmp(self->targetname, "reelo_thug") - || !strcmp(self->targetname, "end_thug") - || !strcmp(self->targetname, "bea") - || !strcmp(self->NPC_targetname, "reelo_thug") - || !strcmp(self->NPC_targetname, "end_thug") - || !strcmp(self->NPC_targetname, "bea")) + if (self->targetname) { - SP_NPC_Spawn_Random_Humanoid(self); - return; + if (!strcmp(self->targetname, "back_squad1") + || !strcmp(self->targetname, "back_squad2") + || !strcmp(self->targetname, "back_squad3") + || !strcmp(self->targetname, "back_squad4") + || !strcmp(self->targetname, "front_squad1") + || !strcmp(self->targetname, "front_squad2") + || !strcmp(self->targetname, "front_squad3") + || !strcmp(self->targetname, "front_squad4") + || !strcmp(self->targetname, "reelo_thug") + || !strcmp(self->targetname, "end_thug") + || !strcmp(self->targetname, "bea")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } } } SP_NPC_Spawn_Random(self); @@ -4050,10 +4032,13 @@ void SP_NPC_Imperial_Random(gentity_t* self) } if (strcmp(lastKnownMap, "doom_detention") == 0) // The jailer of Jan { - if (!strcmp(self->targetname, "jailer") || !strcmp(self->NPC_targetname, "jailer")) + if (self->targetname) { - SP_NPC_Spawn_Random_Humanoid(self); - return; + if (!strcmp(self->targetname, "jailer")) + { + SP_NPC_Spawn_Random_Humanoid(self); + return; + } } } SP_NPC_Spawn_Random(self); From b686657ad0e331fd111ffa54ac74cc344a480ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Fri, 10 Jan 2025 20:21:54 +0100 Subject: [PATCH 49/62] Enhancements (#15) * Moving more "goofy" features to another variable to keep the normal randomizer only to items and NPCs * Added random saber color * Moved README of SpeedOutcast to another file and added a new README.md * Added random jump height at every jump and fixed saber style at pickup (the previous formula resulted with a 0 in 80%+ of cases). * Added variables to control each individual part of the 'enhancements' on the randomizer. * Updated README.md * Added a randomization on the 'strength' of force jumps. It's controlling the speed of the Z axis. * Add a new top menu section for Randomizer, add new 'Basic' and 'Enhancements' submenus, add settings for randomizer enhancements. * Renaming all 'lenght' to 'length' * Added another print of the (X) when enabling the enhancements * Changed the rng engine. This does not affect the initial setSeed value. (#16) * Random language per sound on map load (#17) * Each time a sound is loaded, load a random language version of it. * Add to menu and readme * fix some messed up indentation * Fixes for the base randomizer : (#18) - NPC replacing Desann in artus_topside can properly reflect projectiles. - NPC replacing Reelo's thgs at the end of ns_starpad can't reflect projectiles even if they are saber wielder. - Fixed ATSTs team from free to enemy. --------- Co-authored-by: Mugsworth1 Co-authored-by: Mugsworth1 --- Posto-Stuff-ReadmePLZ.txt | 84 - README - SpeedOutcast.md | 233 ++ README.md | 253 +- assets/Bundle Assets.ps1 | 13 + assets/assets_randomizer.pk3 | Bin 18291 -> 68561 bytes .../map_objects/force_holocrons/grip.md3 | Bin 0 -> 804 bytes .../map_objects/force_holocrons/heal.md3 | Bin 0 -> 804 bytes .../map_objects/force_holocrons/lightning.md3 | Bin 0 -> 804 bytes .../force_holocrons/saberthrow.md3 | Bin 0 -> 804 bytes .../map_objects/force_holocrons/telepathy.md3 | Bin 0 -> 804 bytes assets/readme.txt | 7 + assets/ui/controls.menu | 3524 ++++++++++++++++ assets/ui/ingame.menu | 483 +++ assets/ui/ingamecontrols.menu | 3547 +++++++++++++++++ assets/ui/ingameload.menu | 740 ++++ assets/ui/ingamequit.menu | 798 ++++ assets/ui/ingamerandomizer.menu | 1129 ++++++ assets/ui/ingamesave.menu | 678 ++++ assets/ui/ingamesetup.menu | 3036 ++++++++++++++ assets/ui/loadgame.menu | 738 ++++ assets/ui/main.menu | 490 +++ assets/ui/menus.txt | 31 + assets/ui/newgame.menu | 771 ++++ assets/ui/quit.menu | 575 +++ assets/ui/randomizer.menu | 1122 ++++++ assets/ui/setup.menu | 3144 +++++++++++++++ code/cgame/cg_draw.cpp | 10 +- code/cgame/cg_local.h | 19 +- code/cgame/cg_main.cpp | 21 + code/client/cl_cgame.cpp | 11 + code/client/snd_dma.cpp | 11 +- code/client/snd_mem.cpp | 59 +- code/game/NPC_spawn.cpp | 14 +- code/game/bg_pmove.cpp | 34 + code/game/g_combat.cpp | 15 +- code/game/g_items.cpp | 16 +- code/game/g_missile.cpp | 1 + code/game/wp_saber.cpp | 81 +- code/randomizer/RandomizerUtils.cpp | 19 +- code/randomizer/RandomizerUtils.h | 1 + 40 files changed, 21379 insertions(+), 329 deletions(-) delete mode 100644 Posto-Stuff-ReadmePLZ.txt create mode 100644 README - SpeedOutcast.md create mode 100644 assets/Bundle Assets.ps1 create mode 100644 assets/models/map_objects/force_holocrons/grip.md3 create mode 100644 assets/models/map_objects/force_holocrons/heal.md3 create mode 100644 assets/models/map_objects/force_holocrons/lightning.md3 create mode 100644 assets/models/map_objects/force_holocrons/saberthrow.md3 create mode 100644 assets/models/map_objects/force_holocrons/telepathy.md3 create mode 100644 assets/readme.txt create mode 100644 assets/ui/controls.menu create mode 100644 assets/ui/ingame.menu create mode 100644 assets/ui/ingamecontrols.menu create mode 100644 assets/ui/ingameload.menu create mode 100644 assets/ui/ingamequit.menu create mode 100644 assets/ui/ingamerandomizer.menu create mode 100644 assets/ui/ingamesave.menu create mode 100644 assets/ui/ingamesetup.menu create mode 100644 assets/ui/loadgame.menu create mode 100644 assets/ui/main.menu create mode 100644 assets/ui/menus.txt create mode 100644 assets/ui/newgame.menu create mode 100644 assets/ui/quit.menu create mode 100644 assets/ui/randomizer.menu create mode 100644 assets/ui/setup.menu diff --git a/Posto-Stuff-ReadmePLZ.txt b/Posto-Stuff-ReadmePLZ.txt deleted file mode 100644 index 76ac2744..00000000 --- a/Posto-Stuff-ReadmePLZ.txt +++ /dev/null @@ -1,84 +0,0 @@ -Findings on this Randomizer : -- Friendly and neutral NPC carry necessary items (for exemple, the key on kejim_base). -- Some NPC have to be locked, otherwise, we might get undefined behavior in cutscene or else. -- In ns_streets, no matter which npc (except the ones in the little arena) are forced on a path. -- IMPOSSIBLE to start a new game. -- NPC Spawn are determined at the start of the map, not when you hit triggers. If so, then why does it lag ? (Other are lagging, I'm not). - -TODO : -- Lock all necessarry NPC per map (right now thinking about undercity and assembly, to open doors). -- Fixing G_FindConfigstringIndex (very hard). -- Stop the crashes (very hard). -- Maybe add some kind of items randomize ? Except the necessarry ones ofc. -- Some NPC don't spawn, maybe it's an entity not finished like monster_fish. Need to lock them out. - -List of non-working NPC : -- monster_flier2 -- monster_fish -- claw -- lizard -- swamp -- murjj - -Crash : common.cpp, line 296 -It happens because of G_FindConfigstringIndex each time it seems. -I don't know how to fix that, because if it's truly this case every time, it could be a cool mod :/ -q_shared : upped the max sounds and models. -I mean, it works, but limiting the number of different kind of NPC is the better idea. - -For items : -classname : item_bacta, origin : X,Y,Z - -G_CreateG2AttachedWeaponModel : assert at line 249 crashes -You can't give yourself a lightsaber before trial ???? -It makes the game crash for some reason -In trial : models/wepaons2/saber/saber_w.glm -In kejim_base : NULL, unable to read memory -In ns_street : models/weapons2/saber/saber_w.glm, so the same as in trial -g_utils.cpp line 1001 eventParm < 256 -noweap.md3 ????????? - -Idea : Lock it to 10 MAX, so that 1=Kyle, 2=NeededNPC, 3=NeededNPC, 4=maybe needednpc or a random one, 5+ = the rest -Here is what I could grab as the max number of different NPC on a map in Vanilla (thinking about big map) : -- Artus_detention : Stormtrooper,Imperial,DroidGonk,Prisoner,MineMonster,R5D2,Kyle,Droid_Sentry, a total of 8, Kyle included -- Bespin_undercity : Kyle,Ugnaught,Rodian,R5D2,Gran,Weequay,Reborn, a total of 7, Kyle included (less than I expected - - -Needed NPC per map : -- None (but need confirmation): kejim_post, artus_mine, yavin_trial, cairn_bay, cairn_reactor, doom_comm, doom_shield, yavin_swamp, yavin_canyon, -- kejim_base : the corpse that hold the security key to open the mouse droid pad -- artus_detention : the officer/guard with the long sequence -- ns_street : The entity that takes away the briar blaster need to be 'humanoid' / able to hold the blaster. So locking the rodians it is. -- ns_hideout : Lando and Reelo, but both are already forced -- ns_starpas : The two waves of ennemies, it seems that if a neutral spawn, it's kill isn't counted (not sure) -- bespin_undercity : the entity (don't know his name) that opens the door when using force mind trick -- cairn_assembly : The officer that open the door with mind trick -- cairn_dock1 : maybe forcing everything here, because random NPC behavior are strange (they start focusing you). This one I can just filter the mapo entirely -- doom_detention : the officer that open the door to Jan cell -- yavin_courtyard : the trooper shooting the rebel and the rebel being shot - - -CURRENT SITUATION : I locked the number of max unique NPC to 10 for now. -In DEBUG, the game is way less permissing and throw errors often. -But in RELEASE ? It seems plyable, I will do a full playthrought to confirm that. - -I DID an entire playthought without ATST, and a max of 10 random unique NPC, here is a list of softlock I had : -Chicken robots are really too big, I think we should make them spawn naturally and not randomly. -- Two or more NPC spawn location being too close is a problem, if for exemple ATSTs tried to spawn, only one will THEN the other when there is enough space -- kejim_base : the NPC that spawned behind the door couldn't spawn, it was a big droid and Reelo. Making it impossible for the cutscene to execute -- artus_detention : -NPC will NOT respect that truce when the guard is activated, not really a softlock but careful. Also, any NPC can trigger the guard, not only Kyle. -The guard being too big will not work. -Fortunatly, no matter which team the NPC spawned, it will be overwritten and will always be havin the same path and behavior as the guardian. -- artus_topside : -Didn't manage to load the map under unknown conditions -The path finding of NPC that spawn instead of the stormtrooper seems to always be broken -- ns_starpad crashes during the final against Reelo, I should retry this -- cairn_assembly : if the imperial opening the door is too small (for exmeple a small droid), you can't reach the hitbox to hit persuasion -If the NPC remplacin the two reborn dies or don't spawn (don't know which), the ATST door won't open. -- cairn_dock : the map is imposible to play because the new NPCs are having undefefined behavior, making the discretion impossible and you are spoted instantly when by the window -The shadowtropper have to spawn as a shadowtrooper I think because the platform where it spawns DON'T ELEVATE other NPCs (humanoid or droids) -- doom_detention : I didn't any problem with the guard opening the doors, but there might be the same problem as cairn_assembly - - - diff --git a/README - SpeedOutcast.md b/README - SpeedOutcast.md new file mode 100644 index 00000000..f1a199fd --- /dev/null +++ b/README - SpeedOutcast.md @@ -0,0 +1,233 @@ +# Speed Outcast + +Source port of the singleplayer of Star Wars Jedi Knight II: Jedi Outcast. +Focuses on staying true to the original game to be used for speedrun purposes. +See the [speedrun.com leaderboard](https://www.speedrun.com/jk2) for more information. + +Based on the original source code released by Raven, see README.txt. + +## New Console Variables + +### Input + +#### `in_mouse_raw` (0 or 1) + +Use raw mouse input. Only applies after an `in_restart` (or after restarting the game). +Default: `1`. + +### HUD + +#### `cg_drawOverbounceInfo` (0 or 1) + +Draw overbounce probabilities, G is for Go, J is for Jump. +Default: `0`. + +#### `cg_drawSecrets` (0 or 1) + +Show a tracker for found versus total number of secrets on the current level. +Default `0`. + +#### `cg_drawServerFPS` (0 or 1) + +Show current value of `sv_fps`. +For verification of speedruns for the leaderboards. +Default: `1`. + +#### `cg_drawSpeedrunTotalTimer` (0-3) + +Draw a total run timer. +Higher values show more decimals. +Default: `0`. + +#### `cg_drawSpeedrunLevelTimer` (0-3) + +Draw a current level timer. +Higher values show more decimals. +Default: `0`. + +#### `cg_drawJumpHelper` (0 or 1) + +Draw a helper for correctly timing jump release and crouch jumping. + +#### `cg_jumpHelperX` (#) + +Horizontal position of the jump helper. +Default: `0.0` (center of the screen). + +#### `cg_jumpHelperY` (#) + +Vertical position of the jump helper. +Default: `0.0` (center of the screen). + +#### `cg_jumpHelperWidth` (#) + +Width of the jump helper. +Note that this becomes height when using the vertical jump helper (`cg_jumpHelperHorizontal 0`). +Default: `300`. + +#### `cg_jumpHelperHeight` (#) + +Height of the jump helper. +Note that this becomes width when using the vertical jump helper (`cg_jumpHelperHorizontal 0`). +Default: `20`. + +#### `cg_jumpHelperHorizontal` (-1, 0 or 1) + +Whether to draw the jump helper horizontally left-to-right (`1`), horizontally right-to-left (`-1`) or vertically bottom-to-top (`0`). +Default: `1`. + +#### `cg_jumpHelperMirror` (0 or 1) + +Whether to mirror the jump helper. +Mirrors horizontally when drawing horizontally, vertically otherwise. +Default: `1`. + +#### `cg_jumpHelperAutoScale` (0 or 1) + +Whether to rescale the jump helper to the same size for each force level. +Default: `0`. + +#### `cg_jumpHelperCrouch` (0 or 1) + +Show an additional height section for crouch jumping, appended to normal jump height. +Default: `1`. + +#### `cg_jumpHelperCurrentScale` (#) + +Scale of the indicator for the current height within the jump helper. +Negative values draw from top to bottom, positive values from bottom to top. +Default: `0.5`. + +#### `cg_drawSpeed` (0 or 1) + +Draw the current player speed. +Default: `0`. + +#### `cg_speedScale` (#) + +Scale of the text for speed display. +Default: `0.9`. + +#### `cg_speedX` (#) + +Horizontal offset for drawing speed text, relative to the center of the screen. +Default: `0.0` (center of the screen). + +#### `cg_speedY` (#) + +Vertical offset for drawing speed text, relative to the center of the screen. +Default: `75.0` (Slightly below center of the screen). + +#### `cg_drawStrafeHelper` (0 or 1) + +Draw a strafe helper. +Default: `0`. + +#### `cg_strafeHelperCenter` (0 or 1) + +Put the strafe helper in the center of the screen. +Default: `1`. + +#### `cg_strafeHelperCenterMarker` (0 or 1) + +Draw a marker in the center of the strafe helper. +Default: `1`. + +#### `cg_strafeHelperHeight` (#) + +Height of strafe helper bar. +Default: `20.0`. + +#### `cg_strafeHelperScale` (#) + +Horizontal scale of the strafe helper. +Angles correspond directly to the field of view if this scale is set to `360/cg_fov`. +Default: `4.0`. + +#### `cg_strafeHelperSpeedScale` (#) + +Scale of the text for speed display tied to strafe helper. +Note that this shows the speed after friction but prior to acceleration, as this is what is relevant for optimal strafing. +It is not the intuitive current player speed. +For that, see `cg_drawSpeed`. +Default: `0.9`. + +#### `cg_strafeHelperSpeedX` (#) + +Horizontal offset of the text for speed display, relative to the center of the screen. +Default: `0.0` (center of the screen). + +#### `cg_strafeHelperSpeedY` (#) + +Vertical offset of the text for speed display, relative to the strafe helper. +Default: `0.0` (directly under the strafe helper). + +#### `cg_strafeHelperY` (#) + +Vertical position of the strafe helper. +Default: `50.0`. + +#### `cg_strafeHelperColor[...]` (0.0 - 1.0) + +Color components (red, green, blue, alpha) for different strafe helper elements. +These are `Accelerating`, `Optimal`, `CenterMarker` and `Speed`. +Colors can be set more conveniently with the corresponding commands. + +### Cosmetics + +#### `g_saber_color` (color) + +Set saber color. +Valid colors: "red", "orange", "yellow", "green", "blue", and "purple". +Default: "blue" + +### Gameplay + +#### `g_speedFactorLanding` (0 or 1) + +To play with factors to multiply speed by on landing. +A value of `0.5` will obtain Jedi Academy behaviour, `1.0` is the original behaviour in Jedi Outcast. +**Cheat protected**. +Default: `1`. + +#### `g_selfKnockback` (0 or 1) + +Allow players to damage boost themselves with explosive weapons. +**Cheat protected**. +Default: `0`. + +#### `sv_speedrunModeIL` (0 or 1) + +Individual-level run mode. +When set to `1`, ingame timer will reset every time an autosave is loaded. +When set to `0`, ingame timer will reset only when `kejim_post` is loaded. +Default: `0`. + +#### `sv_speedrunModeCheckpoint` (0 or 1) + +Mode for running from quicksave to a specified checkpoint on a map. +Coordinates can be set with the command `settimedcheckpoint x1 y1 z1 x2 y2 z2`. +When the player enters the box spanned by the two points `(x1 y1 z1)` and `(x2 y2 z2)` the run is finished. +If `x2`, `y2` and `z2` are omitted, a checkpoint of reasonable size will be created at `(x1 y1 z1)`. +Default: `0`. + +#### `sv_speedrunModeCheckpointSave` (0 or 1) + +Create an automatic save when a checkpoint is reached in checkpoint mode. +Default: `0`. + +## New Commands + +### HUD + +#### `jumpHelperColor[...] ` (components in range 0.0 to 1.0) + +Sets the color for one of the jump helper elements `Background`, `Crouch`, `CrouchExtend`, `Extend`, `Optimal`, `Current` or `Cancel` to the given red, green, blue and alpha values. + +#### `speedColor ` (components in range 0.0 to 1.0) + +Sets the color for the speed display to the given red, green, blue and alpha values. + +#### `strafeHelperColor[...] ` (components in range 0.0 to 1.0) + +Sets the color for one of the strafe helper elements `Accelerating`, `Optimal`, `CenterMarker` or `Speed` to the given red, green, blue and alpha values. diff --git a/README.md b/README.md index f1a199fd..6245820c 100644 --- a/README.md +++ b/README.md @@ -1,233 +1,94 @@ -# Speed Outcast +# Speed Outcast - Randomizer -Source port of the singleplayer of Star Wars Jedi Knight II: Jedi Outcast. -Focuses on staying true to the original game to be used for speedrun purposes. +Fork of SpeedOutcast, a source port of the singleplayer of Star Wars Jedi Knight II: Jedi Outcast. +Focuses on staying true to the original game and SpeedOutcast / speedrun.com rules to be used for speedrun purposes. See the [speedrun.com leaderboard](https://www.speedrun.com/jk2) for more information. -Based on the original source code released by Raven, see README.txt. +Based on the original source code released by Raven, see `README.txt`. +Based on the source port of Star Wars Jedi Knight II: Jedi Outcast named SpeedOucast, see `README - SpeedOutcast.md`. -## New Console Variables - -### Input - -#### `in_mouse_raw` (0 or 1) - -Use raw mouse input. Only applies after an `in_restart` (or after restarting the game). -Default: `1`. - -### HUD - -#### `cg_drawOverbounceInfo` (0 or 1) - -Draw overbounce probabilities, G is for Go, J is for Jump. -Default: `0`. -#### `cg_drawSecrets` (0 or 1) - -Show a tracker for found versus total number of secrets on the current level. -Default `0`. - -#### `cg_drawServerFPS` (0 or 1) +## New Console Variables -Show current value of `sv_fps`. -For verification of speedruns for the leaderboards. -Default: `1`. +### Randomizer -#### `cg_drawSpeedrunTotalTimer` (0-3) +#### `cg_enableRandomizer` (0 or 1) -Draw a total run timer. -Higher values show more decimals. +Enable or disable the NPC and items randomizer. Default: `0`. -#### `cg_drawSpeedrunLevelTimer` (0-3) +#### `cg_enableRandomizerEnhancements` (0 or 1) -Draw a current level timer. -Higher values show more decimals. +Enable or disable the other more 'exotic' randomized elements in the game. +Check `List of addition for the 'exotic' Randomizer` below for more details. +Need `cg_enableRandomizer` to be 1 to work. Default: `0`. -#### `cg_drawJumpHelper` (0 or 1) - -Draw a helper for correctly timing jump release and crouch jumping. - -#### `cg_jumpHelperX` (#) - -Horizontal position of the jump helper. -Default: `0.0` (center of the screen). - -#### `cg_jumpHelperY` (#) - -Vertical position of the jump helper. -Default: `0.0` (center of the screen). +#### `cg_setSeed` 10 digits string -#### `cg_jumpHelperWidth` (#) +Variable that store the current seed. Can be edited before starting a run and used if `cg_useSetSeed` is equal to 1. +Default: `EmptyString`. -Width of the jump helper. -Note that this becomes height when using the vertical jump helper (`cg_jumpHelperHorizontal 0`). -Default: `300`. +#### `cg_useSetSeed` (0 or 1) -#### `cg_jumpHelperHeight` (#) - -Height of the jump helper. -Note that this becomes width when using the vertical jump helper (`cg_jumpHelperHorizontal 0`). -Default: `20`. - -#### `cg_jumpHelperHorizontal` (-1, 0 or 1) - -Whether to draw the jump helper horizontally left-to-right (`1`), horizontally right-to-left (`-1`) or vertically bottom-to-top (`0`). -Default: `1`. - -#### `cg_jumpHelperMirror` (0 or 1) - -Whether to mirror the jump helper. -Mirrors horizontally when drawing horizontally, vertically otherwise. -Default: `1`. - -#### `cg_jumpHelperAutoScale` (0 or 1) - -Whether to rescale the jump helper to the same size for each force level. -Default: `0`. - -#### `cg_jumpHelperCrouch` (0 or 1) - -Show an additional height section for crouch jumping, appended to normal jump height. -Default: `1`. - -#### `cg_jumpHelperCurrentScale` (#) - -Scale of the indicator for the current height within the jump helper. -Negative values draw from top to bottom, positive values from bottom to top. -Default: `0.5`. - -#### `cg_drawSpeed` (0 or 1) - -Draw the current player speed. +If 0, generate a random seed during the start of a new game. +If 1, will use the seed stored in `cg_setSeed`. Default: `0`. -#### `cg_speedScale` (#) - -Scale of the text for speed display. -Default: `0.9`. - -#### `cg_speedX` (#) - -Horizontal offset for drawing speed text, relative to the center of the screen. -Default: `0.0` (center of the screen). - -#### `cg_speedY` (#) - -Vertical offset for drawing speed text, relative to the center of the screen. -Default: `75.0` (Slightly below center of the screen). +### HUD -#### `cg_drawStrafeHelper` (0 or 1) +#### `cg_drawSeed` (0 or 1) -Draw a strafe helper. +Draw the seed used during a run. Will draw "No Rand" is `cg_enableRandomizer` is 0. Default: `0`. -#### `cg_strafeHelperCenter` (0 or 1) - -Put the strafe helper in the center of the screen. -Default: `1`. - -#### `cg_strafeHelperCenterMarker` (0 or 1) - -Draw a marker in the center of the strafe helper. -Default: `1`. - -#### `cg_strafeHelperHeight` (#) - -Height of strafe helper bar. -Default: `20.0`. - -#### `cg_strafeHelperScale` (#) - -Horizontal scale of the strafe helper. -Angles correspond directly to the field of view if this scale is set to `360/cg_fov`. -Default: `4.0`. - -#### `cg_strafeHelperSpeedScale` (#) - -Scale of the text for speed display tied to strafe helper. -Note that this shows the speed after friction but prior to acceleration, as this is what is relevant for optimal strafing. -It is not the intuitive current player speed. -For that, see `cg_drawSpeed`. -Default: `0.9`. - -#### `cg_strafeHelperSpeedX` (#) - -Horizontal offset of the text for speed display, relative to the center of the screen. -Default: `0.0` (center of the screen). - -#### `cg_strafeHelperSpeedY` (#) - -Vertical offset of the text for speed display, relative to the strafe helper. -Default: `0.0` (directly under the strafe helper). -#### `cg_strafeHelperY` (#) +## List of addition for the base Randomizer -Vertical position of the strafe helper. -Default: `50.0`. +#### Gameplay -#### `cg_strafeHelperColor[...]` (0.0 - 1.0) +- Every NPC will be randomized during spawn, with exceptions listed below. +- Every items spawned on the map such as items on the ground or in gun racks will be randomized. +- The lightsaber can be obtained early and you will receive a random saber style on pickup. +- Every Force powers (except Saber attack and Saber defense) can be obtained via holocrons. +- NPCs replacing NPCs with keys or special trigger for script will inherit said keys and/or script. +- NPCs replacing normal NPCs will inherit their AI as best as possible (droids can't pathfind exactly like a humanoid). +- Easter egg NPC called `The Death Wiggle`. +- The NPC you kill at the end of `yavin_trial` will trigger the end of the timer like in SpeedOutcast -Color components (red, green, blue, alpha) for different strafe helper elements. -These are `Accelerating`, `Optimal`, `CenterMarker` and `Speed`. -Colors can be set more conveniently with the corresponding commands. +#### Exceptions -### Cosmetics +- Lando, Jan, Luke, MonMothman, Reelo, Desann and Ugnaught will always spawn as humanoids. +- ATSTs, Seekers, MouseDroids, R5D2 (bespin) and 'Chicken Robots' will always spawn as themselves. +- The warden in `artus_detention` will always be an humanoid. +- The stormtrooper shooting at the prisoners in `artus_topside` will always be humanoids. +- Rodian, Gran, Weequay at the end of `ns_starpad` (with Reelo) and the waves when Lando will go inside the Lady Luck will always be humanoids. +- The two Imperial Officers in `cairn_assembly` and `doom_detention` we have to mindtrick will always be humanoids. +- Kyle as in player controlled Kyle will always be Kyle. And randomly spawned Kyle will always be considered allies. -#### `g_saber_color` (color) +### List of addition for the 'exotic' Randomizer -Set saber color. -Valid colors: "red", "orange", "yellow", "green", "blue", and "purple". -Default: "blue" +#### `cg_enableRandSaberStyle` (0 or 1) +Random saber style at pickup. That means you will always get a change to get any saber style, so go for a qs/ql if you want something specific. -### Gameplay +#### `cg_enableRandSaberLength` (0 or 1) +Random saber lenght every time the saber is chosen. From 25% to 400% the saber lenght. -#### `g_speedFactorLanding` (0 or 1) - -To play with factors to multiply speed by on landing. -A value of `0.5` will obtain Jedi Academy behaviour, `1.0` is the original behaviour in Jedi Outcast. -**Cheat protected**. -Default: `1`. - -#### `g_selfKnockback` (0 or 1) - -Allow players to damage boost themselves with explosive weapons. -**Cheat protected**. -Default: `0`. - -#### `sv_speedrunModeIL` (0 or 1) - -Individual-level run mode. -When set to `1`, ingame timer will reset every time an autosave is loaded. -When set to `0`, ingame timer will reset only when `kejim_post` is loaded. -Default: `0`. - -#### `sv_speedrunModeCheckpoint` (0 or 1) - -Mode for running from quicksave to a specified checkpoint on a map. -Coordinates can be set with the command `settimedcheckpoint x1 y1 z1 x2 y2 z2`. -When the player enters the box spanned by the two points `(x1 y1 z1)` and `(x2 y2 z2)` the run is finished. -If `x2`, `y2` and `z2` are omitted, a checkpoint of reasonable size will be created at `(x1 y1 z1)`. -Default: `0`. - -#### `sv_speedrunModeCheckpointSave` (0 or 1) - -Create an automatic save when a checkpoint is reached in checkpoint mode. -Default: `0`. - -## New Commands - -### HUD +#### `cg_enableRandSaberColor` (0 or 1) +Random saber color every time the saber is chosen. Blue, Green, Yeelow, Orange, Purple and Red. RGB might be possible but that needs investigation. -#### `jumpHelperColor[...] ` (components in range 0.0 to 1.0) +#### `cg_enableRandJumpHeight` (0 or 1) +Random jump height with every jump. From 1/3 the normal jump without force to double the height with jump force 3. -Sets the color for one of the jump helper elements `Background`, `Crouch`, `CrouchExtend`, `Extend`, `Optimal`, `Current` or `Cancel` to the given red, green, blue and alpha values. +#### `cg_enableRandJumpStrength` (0 or 1) +Random jump strength with every jump. From the normal jump without force to quadruple the Z velocity with jump force 3. -#### `speedColor ` (components in range 0.0 to 1.0) +#### `cg_enableRandLanguageVoices` (0 or 1) +Random language for each voice line (randomized when loaded on map init) -Sets the color for the speed display to the given red, green, blue and alpha values. +#### Todos +- Random projectiles every shot +- Random sounds +- Random NPC size (may not be possible because of insane hitbox and things) -#### `strafeHelperColor[...] ` (components in range 0.0 to 1.0) -Sets the color for one of the strafe helper elements `Accelerating`, `Optimal`, `CenterMarker` or `Speed` to the given red, green, blue and alpha values. diff --git a/assets/Bundle Assets.ps1 b/assets/Bundle Assets.ps1 new file mode 100644 index 00000000..d382bfa9 --- /dev/null +++ b/assets/Bundle Assets.ps1 @@ -0,0 +1,13 @@ +if(Get-Item assets_randomizer.pk3) +{ + Remove-Item assets_randomizer.pk3 +} + +$compress = @{ + Path = "ui", "models" + CompressionLevel = "Fastest" + DestinationPath = "assets_randomizer.zip" +} +Compress-Archive @compress + +Move-Item assets_randomizer.zip assets_randomizer.pk3 \ No newline at end of file diff --git a/assets/assets_randomizer.pk3 b/assets/assets_randomizer.pk3 index 32f4fb8a2fddc1f0a2971868ce0ff85dd234877b..b8468700bca3b4d3aba848728375d201cc535cdb 100644 GIT binary patch literal 68561 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 literal 18291 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 literal 0 HcmV?d00001 diff --git a/assets/models/map_objects/force_holocrons/heal.md3 b/assets/models/map_objects/force_holocrons/heal.md3 new file mode 100644 index 0000000000000000000000000000000000000000..f172741fffbcfaa340ba05eb25394f05e953fb38 GIT binary patch literal 804 zcmeZt2{7hoU|`72Pf5)w*3V5Wh|f>TN=+^SvJ3QcO5!t86La)(Q;dOX2mwZ@0vMeG za(_zp5Kd~slKuyAB>5O8Ejc;yI^fdSuNOimhUMftf3j=`>)5K&K{ z8rFP3}UkbF&7YX05K;NgV@|a400n#A51-n%?rc=K+Ffkpm+me5L*z4 zK|lzIg`pV42AL1^nLPx9IZ!@28(9r98(AGl90bti(fR0V@XLP!`tk*1zBKQDMIsZS}^ebKl;~~)o>0> ZKTI55AIw~sJd6+153>(uK8z2u7Xb80b7}wp literal 0 HcmV?d00001 diff --git a/assets/models/map_objects/force_holocrons/lightning.md3 b/assets/models/map_objects/force_holocrons/lightning.md3 new file mode 100644 index 0000000000000000000000000000000000000000..5125739687cfaed82b769c60113b630d8fcc1dfd GIT binary patch literal 804 zcmbV}y-vbV6vt0*tysUnkHo~u!9g8F!k`0*t&ssH6E>F$f{0Q|po1fi-~%}N06u~y ztnQjPxWbA$f%Si&H#ALP@Fc(Ve?ITIx0%zkWR!?(r&y{s<95DoIfa|jr3+n;7jLa< zrF`wyDz);yT}+~IiYb0heyi{weYRDI*4Hyp^o8i#AUZUOVkTX5@g3XSyExgoYB=_m znM?1E;u-8%aPAHgC1k3o}4dzdF~&eQ+lZY literal 0 HcmV?d00001 diff --git a/assets/models/map_objects/force_holocrons/saberthrow.md3 b/assets/models/map_objects/force_holocrons/saberthrow.md3 new file mode 100644 index 0000000000000000000000000000000000000000..3352f8146e9e4b263fd6d41cd1137f68e60a0328 GIT binary patch literal 804 zcmeZt2{7hoU|`72Pf5)w*3V5Wh|f>TN=+^SvJ3Q!6O&Sl;!84$^2_ydQ;dP?@Bv1s zB#h1h@|Qrd3NuLZ>j8!XdBCMS)wqWoM1$6!}Y zh^QyfjY;_x28J+2WYQpafv^Y=^8oP%AO^Y70VwzYh#Q!Q35SyOM4%pg0B8&tfb0Tc z5CD0f4TxEQm=%gaY<3{#0%8sz=7eGpn;VEhZUpIrsRyxnfmi^D`G6P{Zy*d}3j#3+ z2m!G$6oc3x^MO9IhhQ)V%137-t3hTXs{@IH0J=OnA6*T8`ATN=+^SvJ3QcO5#gWb5aWuOEN0;a#M_f3h@9& zs2q&W0rHnXu?jOt^6LSH1AGS=7``|#I9NC`I0!g0B)oD2$-sc`FD56Aw4(f61;=1l zO^B!`(2Ys?6$XYdMP$+-cY&}75c2@>1|SBx(E%v<0EioyaE3!>dIoY(l%yvD_2B|Q zW557p7YKs@$op(S%mT!$Pz++T12Gp6a{w_X6oc5@Kn!vtNFPi+h|LSc0zk|M#GrTs zVGvsoh(SOIh=rjT#0HrU^qD;bgE>$>IvZIHG8?{lqnV1>AvRW|k{y+NH em(_3%Og~H

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 DD2$Hl delta 8471 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 pG?fM$z?hnc4G=_-2mWvJh7ABAY$5-*;zy7{b diff --git a/assets/ui/ingamerandomizer.menu b/assets/ui/ingamerandomizer.menu index 109e5c10..4a642dd3 100644 --- a/assets/ui/ingamerandomizer.menu +++ b/assets/ui/ingamerandomizer.menu @@ -962,6 +962,57 @@ hide highlight6 } } + + itemDef + { + name randomizer_basic_info1 + group basic + text "Base randomizer have the following :" + font 2 + textscale 0.8 + rect 305 351 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } + + itemDef + { + name randomizer_basic_info2 + group basic + text "RNG on items, NPC types, NPC health." + font 2 + textscale 0.8 + rect 305 371 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } + + itemDef + { + name randomizer_basic_info3 + group basic + text "-" + font 2 + textscale 0.8 + rect 305 391 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } //---------------------------------------------------------------------------------------------- // diff --git a/assets/ui/randomizer.menu b/assets/ui/randomizer.menu index 70c81523..5120fa31 100644 --- a/assets/ui/randomizer.menu +++ b/assets/ui/randomizer.menu @@ -957,6 +957,57 @@ hide highlight6 } } + + itemDef + { + name randomizer_basic_info1 + group basic + text "Base randomizer have the following :" + font 2 + textscale 0.8 + rect 305 351 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } + + itemDef + { + name randomizer_basic_info2 + group basic + text "RNG on items, NPC types, NPC health." + font 2 + textscale 0.8 + rect 305 371 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } + + itemDef + { + name randomizer_basic_info3 + group basic + text "-" + font 2 + textscale 0.8 + rect 305 391 300 20 + textalign ITEM_ALIGN_CENTER + textalignx 150 + textaligny -2 + forecolor 0.7 0.7 0.7 1 + visible 0 + // appearance_slot 11 + decoration + } //---------------------------------------------------------------------------------------------- // From c63168aca11ee48f762493efb3a4302a8a635aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 16 Jan 2025 08:05:23 +0100 Subject: [PATCH 56/62] Changed the version from 1.1 to 1.2 --- code/win32/AutoVersion.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/win32/AutoVersion.h b/code/win32/AutoVersion.h index b628beca..34840dbc 100644 --- a/code/win32/AutoVersion.h +++ b/code/win32/AutoVersion.h @@ -2,11 +2,11 @@ #define __AUTO_VERSION_HEADER #define VERSION_MAJOR_RELEASE 1 -#define VERSION_MINOR_RELEASE 1 +#define VERSION_MINOR_RELEASE 2 #define VERSION_EXTERNAL_BUILD 0 #define VERSION_INTERNAL_BUILD 0 -#define VERSION_STRING "1, 1, 0, 0" -#define VERSION_STRING_DOTTED "1.1.0.0" +#define VERSION_STRING "1, 2, 0, 0" +#define VERSION_STRING_DOTTED "1.2.0.0" #endif // __AUTO_VERSION_HEADER From a5918f818045ef97f82e0dcdaf0059801ed835b8 Mon Sep 17 00:00:00 2001 From: Mugsworth1 Date: Sun, 19 Jan 2025 08:58:44 +0000 Subject: [PATCH 57/62] Add assists menu with safeStart, startWithPush and bonusJanHealth (#23) --- README.md | 11 +- assets/assets_randomizer.pk3 | Bin 69760 -> 70549 bytes assets/ui/ingamerandomizer.menu | 164 ++++++++++++++++++++++++++ assets/ui/randomizer.menu | 197 +++++++++++++++++++++++++++++++- code/cgame/cg_local.h | 3 + code/cgame/cg_main.cpp | 6 + code/game/NPC_spawn.cpp | 13 ++- code/game/g_client.cpp | 24 +++- code/game/wp_saber.cpp | 13 ++- 9 files changed, 425 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3d8ca80b..365570e1 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,16 @@ Random weapon projectile per shot. Only applies if the weapon is a blaster of so Random texture assigned to each surface per map. No vid_restart required to toggle. #### `cg_enableRandNPCSpeed` (0 or 1) -Random walking, runing and turning speed for NPCs. Range of 33% to 300%. +Random walking, running and turning speed for NPCs. Range of 33% to 300%. + +#### `cg_enableSafeStart` (0 or 1) +Prevents starting two enemies from attacking unless provoked. + +#### `cg_startWithPush` (0 or 1) +Start game with force push 1. + +#### `cg_bonusJanHealth` (0 or 1) +Applies a flat +50 to Jan's health on kejim_post. #### Todos diff --git a/assets/assets_randomizer.pk3 b/assets/assets_randomizer.pk3 index 0f760528f8f392fc53f3bf45c10b6fc901c2ca3b..1c39e5a496b8446e2a4ed59ca4ad170e5fcefc99 100644 GIT binary patch delta 10118 zcmZ{qbxafj|hLy-$qwDDC9Xf7-@z@+A1b!iav3 z?5|*xy+ZmcXf^SWP-~js>W7g~gE}!lpti6S1ru7py7Ie-N4tHcm%Rm1Fzfi~q&d;r z)bcizVAg4j{0LNP&=92=T~6L>&*A)=W>N70dKkeR7$|iU72t4HW_oAmMIQ+Ky>o$X zQe^bbxXFp=wX${CvD>G%CL{Z{5r6Gm@w&Uh*5JID$LqyHMQR%Y90|qPd5q`4#2-Gw zSDpj<&}*;1B5OrnR0nEUPkVwA?wj}ZEjq)1TVij}$KrG6!hKTQAG6ZM%Fgy{Ea@B< z)tVs$yG>J0Pd)Kl_1j<1Vei{Dajjh4G;w8|C$C8my-ky$KGD+V|J-g0`-ay)N2_mo zKsV}5D$SW*9<%jO)VGVZR{G_AcNTCS*Tn#EJ0d)O_H7@^DT?&|&=dU3S74miNBX4u z+oo{VDQcFv_k;Z= z3YMq_Uw~?~)i3`^)<|$Q@F!Y_iIC6;?Zp6mhl?hJ)x#He_IA6P5o_kSKwStI-gyhq z-ab3hWD{~x%~}|&v8S@xzT{Pib9!E?+Tg6o{_fMgQr+rWS|>8=2o}SDiw(sLK^w&f z_r==MyadBm#P*4!rT@I%A1=JIU65KMq0FkY+0ylDd2`PA$_D@K&Oe)KtZWV;O_pB|$I zX(~Ct{RT{h5ChXFg95g#U{_O)$am4B%orm97k&`fSl-WhuU?Bz8$7JnetN)Jl{cB6 zc%7UW1E1uF3E^ls_ucC{T}b#iOh*5WAtpYJ$o)X>a}SttyL;tFU|U5_-pQ&|w~|(B z?$;q|ql9}D9W5-SIz+gM(l$%R@PbGp%-gTZ)bc2gF9=oa&8kPc-&|;<@P=xgg@P^# zVnwe&M1`WHE6s@ekaxHs3pigK*M~!ZlRQ6!d|awBL%u-_3XE#XKKKNWhg7wQh14X zC)xS&cgK^WK#5_TwVy<3jG5BA2-XnR4w<;@bOG}5U&_6_H&DA9>J`4COA-*yD3VM~ zSY9AOxB$$--W{1>8u}24)*|A%KA7;4k#{%rmjw=U`=A8^00m#OwxOj{J_egB^CP3ximnKVJ5CUJz=j zZ~QP;&=p7FwT}dj3)lqAcFI}hrgF=;DGRlrYDyI>oWHMma^|m8y-d6^M2@xM&W*t? zzdc<2m`84$RpscCsm_!U76fpDKFhqY1!(6ftO*Y`Wl&jBks4}o?j3Nw-4{zq(nuI2 z*T{b?2u{I?G68S!1Dj3ucm%)sE~`e19@z&==4ud;Tm-E|ec z{mO+!Jr9x2g=LfD-OxH7tb2_szsjx7aL2DEC)~2UJpm6l4AfBE;&vR-LP1sxUN9(IY6+KZ&Ho(;HP(^ z^wx(no>N%`?E=~HH@tf4H$090UbtXH~HiO_~F+cfgkw@0bL z-_wPXiO*#Vc$k%9qM6SGtnQ}?3^}>yv0VMp;@$c zuke%|mHtf-$zcmWn^ed+DPKHoKsCKhvIk=vf0J8Lu3$&LLo{{vv*@~pEKx{qp}m)S zC}h03DK?b@8tW7CH?G^J6x-V(Ar8tZ-l>CF4LVIGL~omB<-ObqW-aP*%UGZ(QJquT zDmZ$wfWK8Ijt%DV%H`VVCqkAzxx2uUYhvpc^-^t*b(Xar?Nn5r$Kt+W0x@+gdi40@ z9i(GQiQ1_h&ROFX|1|OIsP%lEr;F_Jn3A+9eH5$|JM!ZqdBynBXO_;2%VY|rbdBsi zpK%%l=<%U_T@e?8_WV0R^E^PRUEo1g!hVCg7Z$Lwi=LY!*kX#9sDl$pi1xdk zWLI@uHX!6Ut9dT_tMm6(6s&i{LlltjlI(5Cj+xAII`-mw-Tnjbg$5gFKVD5*s88fa zr{~kviu$rJi>I$wdGf~r${8BaF>*>`t?ig)2TYimm}L)^`%tP^vZKTD0_1opVb=6` zKXyFX*bb&r?I0m4k5e%`lo@|Eq4_7(v=jyGWA?T5KCtsx!w)!1^E#^VNv$A;e7bCO zwkq+!AXj_QI`sEsBsx~LhUI@g}aEuw~%WHhudT#b5a}4 z9hW?wo}yw~ckd7G@_2cR<EpRx_pR65RY)ZuTXE> z0HGi4A!B;!fQGmnEAZWbnJ#gx>I&*U!x4E1a>m!G9C`){#pyzS_=kdk_el#*wqE$q zMU8#<*ScZ(SEKJ-coUeRi<1sp-`w#GtVeXmlWc>1s%d*Tw2rEZY{gJBxqmYY-3$ur z)SRj_&ZZUt`v|=K%m(VDSddG zfEJD$cJp1cym8zpxP%F(~2K$ z0nRhPN#Y~+X$rcO4Q?WRB~yfpFKSZ5&$u8liWDPRsmhkF?^Ptz%U>w87Gbq37l%ii zBHBvxOmW2Kvy89O=>HVH#aJ6h-*!>%RV1Hj-zWM zxXQ0G?n3`IIOjT9tn+Z+hqZb|ZE(IgAh!#)bqY%`720*qFcdX#1q2V}Xs#dC0CIzO& zSmk};*v|;U*%8tVCOH2NpZ1vTJy?v}6rpD*G?DmHZ^bI)czI_8mADR~hVbNHbmhG{s-qxgp$qQ|qGQZE zdp`!^dSW~#xOf3ua`}ze&lK;usEL0~M9@$is#TTbTBR+fawwxz4g6^RGK0YQC8^qG zKm~^xCaAtEdLua!MzooB*SVko8b1Cf?h6cMoCqMIcp0%PpP8zqJ-Ck$m}zFMh~jWH z?(WM?vUY&Sg6C{Wx9fd6WP+%yl^%l&Jxg+J#FkESo=`4@2~sh6>C1GyiGV^A!~!g? z)D(|`YUuo~uObfU4q2+hwDhD#Qwp5O028{I@F#hf{3FcpdPeM0z2!6%)f$&s&fGW{V9j#v+?ikK6y|>6>D%@@7GDoHVuq#4 zh)2YOp4f=<`vnDY4BiyYoIDS}Ohpv;yHD^k<)Z=y(TzmT)9U!hwmv2&)k-DK1FSiv zIp0`Q(=m>R9z3fT^&sV~7dg(uL7woT=GB2Fzr}Yk1I^D-0=A|0X3tCLUYPV*QYi*{ zq6L#B%Lf#d+1ahg=CX{V<>{ruqs4YnM+Rq3w+R9x^ff<=e5vIhOsNuaBy<`c z>gPTl9Upz|l~4~5{x;qE=mj4r3wW|DF@LNG%=)+#%uO)|ANQ#N8@CWM{9=KHmV8~w ztPv%!+Tc2`0?jUHHq+2KfrO|=v76li2L8fAIP-$ryO_*8EeIM9oxr%?ega*4^Pk8YY_zwo8 z|05(8_1^dPKqWJ zWF@wnSm*7``ug1AXU$2Km}uF=%qwSZu5h(_b$xP;JUSXl^nCT~Jvw?n$bYkB^;Gll zQ#x{kOCRmhr@~64vEqznc`m0h{s6VB;>yHt1}fpf;%C1B0Sr|F$lDFPBZEQ$&JCCgJ+B)RBU5zP2&lCV|3_wQ%+!lVm3?&Cx( zb^Wb7ISFffFIa)D4?LrvP^4ccjB74vPWB9n983Ykavi$5GGT3?>5)vv-FXMKZl>S% z{s;bt9Ws?Sqr(~S7x*K7T=2=JuRos`{sG|*MiZV3)u-{FJ2UWak+Eq|iwB2qlOYN*+OgxELy^!ge@tBt$d9tWajs z`*C+?nPB;P&TCYb_H>13sk@4~x5WA8HKmsI(w4#yOTHGFv&LG8TwzSnBCML7dQ>JwvR44^a>ZR{OSn&hWt+7rxSVn>q zT!g*W`|{DMdjh8H%!!2zRN!Sb?2ANx`R}s4dy5e!ojw4E{^%{L@Ph9y$JedW=EfDjQ-~Q&SRt?t%YYh54>OguFltVNO~g@>anepr zC?9x{b#?JX8})E!-FmmvV&>(1oDqkrm4vB=6?JXsipyDsM4<}{O{1y_mnQyx@XzOl zy$nPt^o10JHT4F&_THu~xe7jHsg+c$KbE$@D9B9pTKUv0=pY#)>RE@_+ye$z$_9Iv zU;yP6o-pN~&WvR6yG2v5k$}*q{U6sPf;%BWt*GFR&2ttG1&O zK7}$aJB*I1W_xp9=L`3fEiN3CmGf6Nk7+oc#}dyW)G@Zv-%Ci$^chFD%T9Em1G;H2 z<~He#kvO91t^=C`M>~<(26Xm}2^DoAaFa5ZRPYTgl_Gv;eqK7xEn~DchiKi#or}XO z#Y7<=bL_^OR_D!44`-qvF{cHK?^Vtv8oXT34l(F;jr$F?ID$;ymN%a0K`)U4GZR%% z%WzS(1_3E|u~O)8^T#&05Af!cz*qT>mjm5U+SFdtM=Uh|aIS1VDmz<*!b?~sE<8lO zd{#p5yKXd1_;75+SU)gzF)!y)DYkk+S~0am8RXqFQguU(*?_n@?DZSp-+BIvXNv+t zjqy@bCyz#<6DUF+NunJW?4l?p_xuON-a8yf-PqXTxo*o0LLqca$_l!2fU+)^lBeoG z_W`DcNktTwilZbofl!t&(w0-fkEyt0*5AN9iGDaeFgxvL{E&hrc~T?;LnU8jV2=D! zd|oa5FmT;@s=s{0VBL*h#(6Sci8mW&#QI1#na^J!##F3ov$W>*{5ITxE}x4&+i1(x z3l`y=r&HQaVkmy^o7IdsP^qzlzck?8r?>Iw9H%gBkPMc`NT8w{B`TY=L~B=Jw?t*x z#GEXmrm-)*aPVN4t#uh08)zC&YaMEK17$7W7Hu4RuC{JqFNM!(vfa@J24}ZWvRMY% zw5oIwHD4BojgPfjX(Z>ZeP)_cfUU{?hL#8C>ZF^`ulqT5;og7|IK#g@G}RqGpxARB z8?=@9Fh?u}^ly}nTWgID$nW}R4{UvrnjGI6PfNMa`A!k)NW^5dB9hQ*=f+^n>P^%g z`GkEAhv&-9l-T@PoT(V8t+%RLjfTSntGU91UqxcYxY1L|Si1r}zb53HIBIOslSxEb z^Wwz#9E7WNaQdqcAg!%!5X|tq%F7hd@;KY_xO?f_WQp8?gVeQEOV7o6A&35yV?Zs= z5{Jt=Mgl+fz*qJ^V2SPK(*9uo)N`?QaMK<}PB5RipI~jNFFyxM<`if6A@tXh@zhIF zu-WvnffrOIg@hrJfD*)E#F>~H{&QkLPawV;EVIJdCJL<*;6GVF8xF(z{kAW-+YaFv z*>o^B#!5uKfmg5dz`&dDY0ZQ!UxR^e>ow>Sg~&*s*zUq+OnV>1ZVQK6s51G+E~ z+zqLA(&w~kfpZ1T%vI%ZUc-kY&fhy%PboHyeQ<~oa11*wGI03G8PQg zA08nWuEA2J83TcFTRB1mCEkY1FaZ(EbmuQ(n^Wt}hq~~)%f23LF?i|3sV&F{Qc;D7zruZFus+rT(yKeN*mk*CtnRefWd41oQAsj{dd_c-hpsXgGVm}d3{ z?Xv-nT(!==){Szdh#1I6G0a%T6A_F*Y4x}r@KvJ5G9_k2^eiB%+0tbtQ1EfFwK0li zN9OxYO36%gdbIw?3a()`YuRE>TkH_JmmesRG7EY)+cxE*3%aAHuX?;0W@uDbxKujT9!>jY1+h0{#m0jqmqO7 z#Zds|A?v>LhKSj9f_yQjGC8R#H0jW*dtBC3V8MuZy5hPFR`eT7mUW&`k}F%Oug8%% z@<*D{nEBzj#l&STStI=*xVU$1pf*;j*1J{j!SuOQqhZON z^y3HJlWXZ#h0O73#=@?VlU<(I#`k?YT*G%s7uhltKF$#Ie1yYo<20NAyU zFb8stbH0lv)~!+&?;KTvqcy zvy|1`%9_lqFND)LsMA0XQFFb4>Kh5=NW*2~BpWBu6O0+Qw`iuSVm_Puz=ZjwP|&sB z<;JVI^@DPs_nr0l-gx*_gZb$xv(JR;AGmaW%KYFY#@-lKf{)qO8L8WYp*zLw{Rc2j zPnlb{cg{yT1*!>57e@S2d$JU{iOw$R_~ZS&#c4=i+(;9K!^0U?boU-kP%F66*f4sq zz_xwSY-J5^psCq*v2j7tF$#9>#}|<_ z;a=0xap63aug84);344RouV>z1$=i|2KGFU@>I<>uX(8(em& zzYKRyqQE;$#;7eU)~!6h^L)U_XvN@xu}996X)ycAc@3IyU0U^Ix5W%EJ31KOE3_6d zSbNBI1e254a21WH(NN1PT4B9j#@YfmXQBPR1Manz>#-8c~Kq;`(gaSjxO#`DMd9E)*f z7jCR(d^8T!Ks2f5CKftk^cQwURNGevW{Tv6|NOUr{_OJN*~AeN?J0FqaghRx z1U99vHSgW00ISwOp5W<^`hsKHvP42<_Y$^HQ~V{^@o1&e{4;a=GMJgGk{pG7l(#w7yF7mP;grd%@(J^z^VBgd>=clHhk4{=k*v?^ab1_l(6>G7a8da z@}@|UI_Sx)dxMCh@2<6((+@{4sZsvbA*ns3RlLJ*N=n5^I@>B*JKKYN;kUN5k#+Cb z=$A-QS5&B3c20IT=UDx}-2XhUntd5v{VxQi``;1Nmn>r-=HCp8^bdnN+a{Q2(`$Z& z4#49eu6i_Eb9p*;WjmkcWPWwW>!J5h`h62_y|<-1=3JFpER5t@P3CzW`N~U4EOFwzwrSOCVr1nrTG6CP`C(PbccyFrD#aj?& z34Y61O_$G>^>SSZzNK*51+iL*$&GKQgyhrv`B1DAf)B9cUqq`2&=riw+PD%wKogb# zN4IafK)K>wF3Ba$=L{Ta3pk!}G;VH3!`WxLg74~gP>S8Vu{FU{N$;rv zT)5wN|4FSH>(*9iq3fI9X2e2)S^hy%t=&-Il)rGQRRac`{4aF`3(ozQii8Je{7X?l z!1;ew#sDH%;GbwZ5}5CwHbW2zEcRCfA%TVdioQSMf1G~GKtcxdn*QnjU*rsQzzqWZ zAz%OPqILy=JnanaoNUY-t=!GLtXLeaoIF((z);wr|9kpM|6D9T2AvuNioF4Wu>M;b z1XA|TC`JZT0RL1G2wM}sLjr+<1VAA4|LB!a@VAPCvzg^Tb^g~HUS1LIGYBA18a)Vv z{2%G2s=sMRGdrjMHAxSLlOcfu#)GPA&M-s)6aHNf9~3YVFx2ul>15^o|1E0-I#V}? zfIurO|Fi7Wz~8W|r=7?DQ}#bO;{RM!-KoDxw+t-Qf6s;u6-)%xwwa;yr~SJb-u)v| zVZj;f5HNN|9xC`Rq|B)L#~%KdO`UO$3dW}RXJz#?%Cr^1AP_Y)2*mUsYh&eDCj~3Ec$rwA*u?P&zT;HN^j_ZIn7aE&t+C~RI`^59Fx6}dI4D) znO}p+QofX-H3w&ygv)fR@(Mlqj2F>1h)X7@BYxmTf-CIEc^qqq%?J#9Xn4H8{?-NV zkiIJPS#7p?s93<`8@)7gGO{xm-2c_O3NX z2WcOu;;DI{0IqL0F^D~U9MK@&J=GcJqWZ*-3w7C8-Z3p-{S!XwzUBX<>=l@9A)u?; z&!-Ydv{4`BdsP+wqjqhC`1)F}BBK1mQfWk=b8?5&I=Qk&=SwNZ2I1ee&ctIH5=A1GfXhyQ3}(!sA}lFn_#}pEEE0nP4lnL0GvQBd2?D zUOfS9!^OLg#7zr~G&bywFgTHc5W_RyVl%e73D1`~L}CR!N?pbrJrmCx*l=DT=^khNFn# zgz>|gRJ?~p(ID~&lNz;gWr6I-b+9Z^>#sb{5KCkSnnezP)KXNj;R~ z6nwPXfx!W)0xNFb4i&vB$0boP+qT_41oCqEtm!Jk^~dNQsi`^LGuyf7*xK!;!*3u+ zjk{Fm==S}MmQt=JWGD6KLv=Uxp>Ol(;tCh%$)ina`#b0ddD5D4iqaFq?_)^wIKQug zKD_gj_eSXRA0>q{4t?%HyXrb7Muv6va=E;-XmtH9s&j17P`B!HfOJY7oFVN>3Cx8I z^!3e)>Mw`A<}FOIN>7M9b%vsD>`KPd*Z6Xy};7*k&kM)1xVINYjC(ZICgvH z&2BJiWKhYLw-)-o7b@HpxLUgsTH4%$7QMBwHv4*B>* zKd-df)xNFbu)8+?iigyB`!o+-`+FBSX(uM+Xxi#pLrlLd0=Z~4%*fs9asZwSO&dZ0 zdBeR$dVt4CppZ@gQ;{Nh04%$Be1#vF!ss<16lp7M*2*vT_=Lo4U89e*icD!&a9j7I z8IO;?l2>nb>RO}rPyCe`+T!cV0j7xb>~X6}n@9#kzsB3GJ(o7V#dS!UXr4}roEwH#B7 zcz$!-$x-nff0)>5{C*ZZT{(q<%P~8yOXi7D^j$fAFFHC!@}ie^57!; zE?vWCI=K4+a2o8H(NEWj=K4b}<&Odyyc=DW(p<*IG*aZ;L;`F4s4ut6Fo^l}{IBsQ zD$jP^cejKC#ptVU)Odjo^G7%aAA(0XYH88tbrnMpv(iOC7C=&h7B7UcOFdiW1hcy# zvKf?i*YiZSCQ%Bt#LESQASgn%YZp3&; z^qF@sHz?Li@_!0>xA)g<# z?-EE^DsjiE0$U|>l%%h|qFFIlXvI~&wslM>`8ePwKqLq(P7kl`TjLZ-&pECpz!(YZ7b}xW3mp;MGNOd)~5*^jVA=L4NhcaN? zL5#;_%Hi_JF$1}ODumCO^}r?ickSWG*-p`sYA$C@Sb3$TezAC#9@i8FwXwd97(^oa zMM4k6&+){pI2_c`+O}OwbAT+IgLS7HkcTZ4=RW;~cB(vOu+)|0?CyXu%ziOvEgCTm zF9=v1=lB_xaK0vFabv0xk&vFyP}lVQeP*hE;iVF`mL2K1`|bS_Ep3Kd0q!Vzi8Zpk zUZ$F?dJ6<=Ay-!SmX=7NqG+_oh5Tq`eCv}fn4p|3DOXJWbFnX?eBzCvnmKN}I6IsAj;J)*3l8fVo6Og(%D1?W_HnkyQw1THo zUMRIYu%VwkkojmSoz~Am#-*CARteW6B=WOitaLbnu52_*=WcbTK_^D~itY=;oOy@L|yI8ulwA$s4hE9-| zOl(#s>11k{wd(k|hT-n7i(<*U46#h692bN3${F?Cf6^rhmg(2qQ@yS-R|IDFtCigt ziHqX)%9B}JHiCRs@=>xvgn6}*<02#2f)O4U(I@c+xZDG}Tn+M)i&vFvnx`D)LU0s@ zrQ@{*b`(>*f-}_8SX7**^1DeksEz7rGa4DaNt$p^M{?l^YSD!xZ{yLAsB|$ywJxJ* zei3PobibB`Z@OXsI3>SxBMaobj4>MXDlm}JSySw)3)k`a-~v?|B$R+!wU?@EJ6L$0 znhQ6xXeu9ksjRHo*P1^=!T;iSJf3fK!TD_-(T@r_(kW3Xaur;Z<&A3h z`#Z})av#Pz=uZP7rB!t{tCWk%Y}$Uiq4e$bxv>PP+U*gSk3|@viNiqp_N5|)SGQQi zMJRDdViIy1VrYIx`&8&=Wf9cE=VMXq*idDbjbruoq*A@_{t`2Ajy?M6b_asF=uXlw zZzCsXSfBBI_eZ~RiAsC*0U6|#mq82?iKXmT3Y8wUvl6*=y+l(Rp1bS&m3QjdCY!d^ z3Mx#yzwd{3uGa<&U9Esic$&c0=y!HLc3@dy$SI0Z>wSEA9U zIbl-G|Db*)0l_-3DL!hDT~b@OWI1#ilwZ|s;aeiY zXkjC(hObyhmWLNC6tV34^{3fok|nRDQ8Y{!Po@)RFzyVS&%#Rq;nxvgzO8wuC+&(! z^$y`^{wgfeVbKofjV7Q5IS+`8j97iEgCY8T-U(?YH{iy4j) zuQ-lbOA9`6Vo?T1s?j=uPp&ayRZAAR2j)vy;9ly{(hscZS#_qp!5%xJj71ROf!IzE zEwf_Sm)q3Qm_!Z&oVf@{oVuXCg?0$zw|8(^!odNgFUV3jXi3WkiopXhPE?>FCIK*_ zD}Z!Onb-J=4hE@Tt%Tb1bteK@r8xPx+H3;PZ2mH>+d88vLp>$5F_*gcH{qCh>+3Yl zd2-y8a`)-^jT0#<`#~n~7c;PY3t?=XtP3f6M&RZa>Jkyqf?^yxQ)2Qdh(VCYUs~OW zGvqgRSd!Fx7*youNJ*wClPlY`&~So9Ki zNis?ZQ%ThB^i5r(`2NhuU=~R|+8RVIX){#MIFQ&`{|`j3?=v5GFPjVn z)?SYe8^KYqht=dj7YIHqZ>xLt_YAF-qV}C+#nqY0`?@0V!z&<1`qD_}m=5re#A!lF zh0BYt0k(~JZS&T(rjGHfSCWqcKo+q%3Pk`bS`7Sn1ZzQ zWO@_H-%$WR=*NQZ6rBQ=k%QH7Bc@mmhC_60BXZRk1x#k;CO@sgpqN@=6l{dz>2n9$HW{ zw2NM%jIuuT$>gS3KAP5a>1(;2*%ux2g(Q=U-LJ`iKq`M251z5m_}wOQybl!%wVK3 zvVSI*25D%PlD;@H5k8nX`?M}6DbxOl^RPoFJa{`@y#B?P6qO<<7Gcw-Sx0Q^oZS_e(^zNLutk50~c0Hn@yhGB3aCi#Sj3FPHyHj=6hr zWb`Bv6&SoH@W{|~^|;9z0QNB^M|?|q0>IJ^{h{Q616x`gn@!hW9a*5Xz=atHdZq|^Mp|EvD`UbzO5g-eRXz;QdtYW za?8_;Wj_x^AOGT2KGaiJK1b4@4|sX$hc@nn|BF(LwuO&xLhBJKN$w6>d=_fQ4YDOF zLYadfAie~M5g-#dO-v7dSu~KrwBmgfq%5ja^1bRF+IDXlpUcnuU$5eo=UuHUTlI8C znL-!MZfAD*z6d`q#FI1f@xfGa# z#CZKU+QBX-7JFFCqz(*KpQVwXxdh(ZkEgc>_uq$&ufDjNt`6H;)!ohGP)i}Rg&WYe z^bOQpE|ZwmB7X+1Nq=r5h}JsOMv1=s+HMyp?`w61a9nNR@w9)CKU=`0=ta~WS!KuO zx1;P2t}w}~mmi8$j8bc&;#54e23t*DVXb{w&t>STK2?kWBlb=-!&-2p`_q9&3evKg zHxY-6aQya7@N9ixVYuU9s^z_2zy5_dF+eF^>4j|H$DRXtpuaS!raTP8jIaCPf}fWL zNfe)?M&2PRjBDU63YxV?tYFKa7mt;tW6dC{pGQS~ZH13RNl#caRQ!S;E}0g+a@yQ< z)|SU>_=U7cAZ7#8kg@MJybP+(!6QzzM6IaVrYK=^UDBW|#V#~Yo&7LeP#R5ga_Kl!Ck_Al&|C66+t{!J&V5?Z? zOXS$2Wv8PXIpAKeA4}(04y~p-CMK8rJvTbJSZ8YA;F*>tS+wPbZOsWCxiy?Fo*}OH zWSnbFswG>(%TGv9FXUR+;e~I4l*5Af?55|yN&e1Uc*d;}9W=K~U#lHYd`|mfH}_6^ zIjceFtytvu#z2Y2>HdX+VZY-{n?dN}kQrumdw87etVGF0jPirq;YRB#9JLz5F5fCk zP}kf0o$qz{P>~K*yL|L{_^@gNpUjVa)QGSac_^Xwo&s35v<6Qv=W>x8mX_98K&`$& zwB?urF|j1nTjDiqp``IBL1kuR;FTsqFs^bGt4D%5Dq2ff5U%z1i@}MmF8wFz3h29q znmA4HgCF?E>&Dx_y46n6Z`7CD3o4OA(Xeh-;w>kHxv~ro3HldW-lGz+Fu|Cw(S?eX zoVL>gv2-+W=2TvjB{{L{nPo61a}1OL(LpZ?n6J8|_P$KGSr**lJe3%x?qY7=*{8T} zV;CnvBUe$P7#bX95U=G{grv?4e%9^lFJ2H?wv(2;{54pf`n}MI{f>S(M=)2yu3+Nr z+^?er8TiIA7%NTQ)($fd2;vc6E1iv0k8yAHa8|HpNjI}D$}!mLV%*ox$a+-+Kvh%t zKnf9971X2qIO3B*h2nIYqKi+)iv7JDyk)lZ+tF&`m+=*s zEi5txo)1#bm<%^wZ)JIh|eThfa>a4yW+!%QF zOS+5|j{>Wf14Xl5%|D2jJ4V+Wovl6Ti~Y)M}=_Z6;0)K;QOstI(K?j zWq8NP+^)aaB^?IJ_ho|Mizs2BTRl`G%?q;f#H-xirVkPLXmoK{(?~8s99tsiR9wa7 zLU1{f_)(_fzH4@FHR6E=IR{vR7?}TM+VlsVY_o2IaKoU=FC)@tOn|app&+C z!V{Q*i!J=7iH02+0_QFZ)HIJ$6P3kxoYxe^YPqSmyAyVHEWunESgeV}AZA_Z6C8pK zaG0ZFAMxzj&4NaGQBtV$Vp!G193nOarAHLxnQnSk(PGqkkNJ~`?oee`!uYkndn=GR z9B_AjD5E;$n9#XAWuhE$jxIEiG)Qk^S10fi!rO3a*jKpUxOwOW(&=mb1M(!oj(k)L zZ2SE#(Gw0Gaeo)oYR*YNytvjiQU6&~^XAvpr8wlL2nDaiC(6t4Rv>Qk^T`Ti&Y%Aa z5!uLQaFcjx!+KX4U%KSTd*WJ;QT98^oFDeQ5|4R8-Q?3bvKNWm`Mu$@0aQet1hLyN zy=!*7Y{ba`9SO@FKoCcIS)F~kJ=^KnSf+6ci=!_HmFz z$#05VkQI-Ro2i4XE+HXOeS%k^I?FQsgfL|T@l_R9sBjw%w(323RR8Rq=jNJKsra;R z|G|^*Nxr7)_+rD-foP1%A)EFsD`L1&nDNz$&XWI&yxD0+AjU}588;W!GO04Ls=6WF zs=ugVXzbHroiWp>A>c;fO}Wdy^KM!U>s+oxSic_=!x{!-;|a<+y?`;JJCaa#XRT4& zI}&_nS!1394by+9Q5{UxSMP3^H`CnY=A9;7uJ91+3RBy5cfrOh@gpdZZ!2CFbKoed z#n=ZKnJ zUI2rtAeDQ*IS+cq8%8P5c;lB%vm%vBLi|J7WgQxzUSi5NEwQO-NF3Hus^N@tQ~k@a zT-mVxs|Ax|epis5>U(b6X$|MZFWzPh%*^y2k5sVu_yXGdIss3 zt?dL5ErnjyjbOfG^%$vkkGdQ9vaX1k9Wm@s49b|(;jVQKy%J@1oh7b49CW?|!O z)!S+SvQ_r%D0kys!fAQS9gP+lyHapfuX9lmBYPN76kC(sT@~9U1BRzaH4L3ns4n)K zyG`jt_Pu(|eOG(jD)>4$%dA+GsLFKM4fbh~?i`dvoHWAbiFl2k0f(YU;4|PrD=U%C z6Og#5*RsdU;M1A^VAD96yoqVwQmGR#!#o27b-lF-n6AH=YM)HraYO#WL_n9`(r8v! z0?rhk3x^yrzzN6N9faH2k=0L6;YjfY;fWrXQKfrVh`5ppDU&@d?K_U+H94M0ug`*V zV17-qg+;JB;1>;*N8=<9M^Yp%nAVzYTyORvSEvUX2{+V0%+OdCRX*{?^nwW82t$BO z?=NYj7lS#p$5%;Q!#da)>wp2D;EEnb%^jy44v-G-o8IYD&q*y|I zhts!@6e-Z(q;d_fB#WLKcB~qN@hFEa(m%PXmMRdpGW+m%7!2w2dg$EhvM>#$?;J%? zR7n3Ssck*$XPUgXv3~<{STQRhdvOXBue5Yr3tkF3Q2Ux4%ZoG|-lAt+nb|c)_1KQ& zZTat`4esh;^EG~lO_u=QsZqu=Be2>|@xR)o=j{)TMbE}}<;a>}u8e{1W4~K-&e>Z; z$*X)Nd19W((|WgqMjDC<{OW9`A(d9Uv)N)yqYMzyR7KWnJxrdTZ`i_#Ka~Mi=V>EM z_(R8ZOef5-hEBWfoazHuU<=}{HlSC08~u_PCb6ioB>NsG&xC_sWe-yJ(t#f#;x>Lk z-!sRn@JzM|q8hB=>ByxG6_%(|UEItV);gziKcKD(ShijlUda0uW9>vDQ5oB{E6Uvf zV>XYr$^_9z>bH26%Y#Vg^cIlxPQ%N2ldt}VZZO1RPW>u<#ppOb`v; z0xxI*iw#cv8IgcYk3PYQj@Z!Q_y-jzic;~!Q}5;$@CbiLKV(Se-&A%LcBACgXjU%u;fGQnn<{Cm&nv=F>V;yHC(Rab^OIsAgmy0Eh@q#n zq1&|h`(PLBHNd`@a_^n-d@DOHqHq6@4V7b)H-E^+tV5Bs8RlI%Oe~>yWH_53AYhkj z{ruCNxa?!vH*%t9AnSsrkU%KBL(Z%Wnjy1mvno^l=?g#?u95l77ZQ0QQ#ZVH=^Q=J znKp4gbo1ZH(YyAcvuuYSh3TM_)XCS|6zAckE5uIQt08 zy0Q|Mk>W8!g50@E+vq8ia0_NJ>xsL=;j&b2cfWZL4{VP1O5*21CC@OJEW>)>&eod4 z6}TTHCxF)CzPj4}?IG|d8{;FI>kkq^cYAE2-J3jDQ$lpw@NyRX!GR$UtWsx@LY+wR z8oK8wRA;18RSSNFX4`9%+`U&=vGv5Qkp5Ah9dGQj*wDLX5%<%w#i{jclzP^x(!&O) z9v4F>DgRNPKZ840Rmj?GoKp|8K}t}ToVvWgFu>HC#HES`?e0yT97AN9Os%x)euc*Z z@e6N@ct{9^6K|l~pvcXo!H6-&TPLNC7V{NRJ_|9UQXXRJ7Lr&XgH9*56KR)>na;^nRHoe4(&kc`@H#p)gTYEMl?j>;GDg#xmL!rL18Z%AwZ^h z3ha&fE`Pq?S}u~*P1aI|9?2&~!n7?76^?P}@z=lIvP`Qja$^f-^ux3ixPRg&n6$}U zAOSw{6NC`0^EdGz7ck%!>G8**RnOv<|A8Q}n+CRcaQEjBQcMgg?HRar*oV)PDOwT& z&Q%Rv0Fm~ZtBF1TJOwcOEz<{#+fe`%SoSP6MK(BXO|>`))GYrPcqSnn_eMLB8|E*&i9(uXltpif8DF_8d6ucuk5!MgJV=VS`~Ns#M1X!I z#Qzo3zd?_kc7h|pz6T4NDt7lf@49;LRxJeaPUUR^^bZB0EBQk~kfkYB1b#OBF9tD{ zK4>5jk)STN=Jw6~F%%?M;XBW}%o`gt8P2|j-2L?l{C_~mGY9EiU7&*%FJMW{gMitP zo+mW)ak+x*RZ<-hz-*21@ZdLp2}q+g0yyCx^?(S@`bT9UgH!)eyr|%uzbf@R8d&HL zGD*cl2Mhca>gZsJzakkOEb>>(K8ydF^GKz{0Q3LdG{69pz33>R=G)#d9Y({^JNskUycKe{(1QaKM=Gb;!@PLH`4Rtargetname && !Q_strncmp(ent->targetname, "st_guard", 8)) { + ent->NPC->behaviorState = BS_SLEEP; + } + if (ent->spawnflags & SFB_CINEMATIC) {//if a cinematic guy, default us to wait bState ent->NPC->behaviorState = BS_CINEMATIC; @@ -1412,7 +1419,11 @@ void NPC_Begin (gentity_t *ent) ent->nextthink = level.time + FRAMETIME + Q_irand(0, 100); NPC_SetMiscDefaultData( ent ); - if (cg_enableRandomizer.integer) // Encapsulate max hp changes + //Bump up Jan's max health a little - skip random health for her too + if (cg_bonusJanHealth.integer && !Q_stricmp(level.mapname, "kejim_post") && ent->targetname && !Q_stricmp(ent->targetname, "jan")) { + ent->max_health += 50; + } + else if (cg_enableRandomizer.integer) // Encapsulate max hp changes { if (ent->max_health) { uniform_real_distribution NPC_HP_Dist(25, 400); diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index ab154631..e623ae96 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -17,6 +17,7 @@ extern vmCvar_t cg_thirdPersonAlpha; // Posto / Randomizer : for the first weapon (It might roll a stun baton again, would be pretty funny) extern int GetRandomizedWeapon(); extern vmCvar_t cg_enableRandomizer; +extern vmCvar_t cg_startWithPush; // g_client.c -- client functions that don't happen every frame @@ -650,7 +651,7 @@ Player_RestoreFromPrevLevel Argument : gentity_t *ent ============ */ -void Player_RestoreFromPrevLevel(gentity_t *ent) +void Player_RestoreFromPrevLevel(gentity_t *ent, SavedGameJustLoaded_e eSaveGameJustLoaded) { gclient_t *client = ent->client; int i; @@ -733,6 +734,25 @@ void Player_RestoreFromPrevLevel(gentity_t *ent) } assert (i==NUM_FORCE_POWERS); + //On resetting by loading auto_kejim_post + if (cg_enableRandomizer.integer && eSaveGameJustLoaded == eRESET) { + //If start with push enabled then apply - have to handle it here so it applies without having to go to menu + if (cg_startWithPush.integer) { + client->ps.forcePowerLevel[FP_PUSH] = 1; + client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (1 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + client->ps.forcePower = FORCE_POWER_MAX; + } + else if (client->ps.forcePowerLevel[FP_PUSH] > 0) + { + //Clear all force powers - necessary because the initial apply for startWithPush sets it on auto_kejim_post so we have to handle it here + for (int i = 0; i < NUM_FORCE_POWERS; i++) { + ent->client->ps.forcePowerLevel[i] = 0; + } + client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (0 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + } + } + + client->ps.forcePowerMax = FORCE_POWER_MAX; client->ps.forceGripEntityNum = ENTITYNUM_NONE; } @@ -1683,7 +1703,7 @@ qboolean ClientSpawn(gentity_t *ent, SavedGameJustLoaded_e eSavedGameJustLoaded (spawnPoint->spawnflags&1) || // KEEP_PREV g_qbLoadTransition == qtrue ) { - Player_RestoreFromPrevLevel(ent); + Player_RestoreFromPrevLevel(ent, eSavedGameJustLoaded); } diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index c83611c9..6581b1ff 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -106,6 +106,7 @@ extern vmCvar_t cg_enableRandomizerEnhancements; extern vmCvar_t cg_enableRandSaberStyle; extern vmCvar_t cg_enableRandSaberLength; extern vmCvar_t cg_enableRandSaberColor; +extern vmCvar_t cg_startWithPush; extern int g_crosshairEntNum; int g_saberFlashTime = 0; @@ -8718,10 +8719,20 @@ void WP_InitForcePowers( gentity_t *ent ) {//player //Don't initialise us with a random set of force powers please if (cg_enableRandomizer.integer) { - ent->client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (0 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + //Clear all force powers for (int i = 0; i < NUM_FORCE_POWERS; i++) { ent->client->ps.forcePowerLevel[i] = 0; } + //If using easy start, apply force push + if (cg_startWithPush.integer && !Q_stricmp(level.mapname, "kejim_post")) { + ent->client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (1 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + ent->client->ps.forcePowerLevel[FP_PUSH] = 1; + ent->client->ps.forcePower = FORCE_POWER_MAX; + } + else { + //Don't need to worry about overwriting force powers from save here as they are applied later + ent->client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (0 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); + } ent->client->ps.forcePowerMax = FORCE_POWER_MAX; ent->client->ps.forcePowerRegenDebounceTime = 0; } From 87bc3d3b95662bf417eb7cfafff2263ae0bccfe7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Sun, 19 Jan 2025 13:13:14 +0100 Subject: [PATCH 58/62] Added encapsulation for the assists and redid the UI menu. (#24) --- assets/assets_randomizer.pk3 | Bin 70549 -> 70985 bytes assets/ui/ingamerandomizer.menu | 409 +++++++++++++++++++++---------- assets/ui/randomizer.menu | 421 ++++++++++++++++++++------------ code/game/NPC_spawn.cpp | 8 +- code/game/g_client.cpp | 3 +- code/game/wp_saber.cpp | 2 +- 6 files changed, 547 insertions(+), 296 deletions(-) diff --git a/assets/assets_randomizer.pk3 b/assets/assets_randomizer.pk3 index 1c39e5a496b8446e2a4ed59ca4ad170e5fcefc99..f859ba40b5f0591cc6d58d26fe9aadd43819c53c 100644 GIT binary patch delta 10491 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 delta 10140 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 Nz=A-dD6j6I{{vQtargetname && !Q_strncmp(ent->targetname, "st_guard", 8)) { + if (cg_enableRandomizerEnhancements.integer && cg_enableSafeStart.integer && !Q_stricmp(level.mapname, "kejim_post") && ent->targetname && !Q_strncmp(ent->targetname, "st_guard", 8)) { ent->NPC->behaviorState = BS_SLEEP; } @@ -1419,11 +1419,11 @@ void NPC_Begin (gentity_t *ent) ent->nextthink = level.time + FRAMETIME + Q_irand(0, 100); NPC_SetMiscDefaultData( ent ); - //Bump up Jan's max health a little - skip random health for her too - if (cg_bonusJanHealth.integer && !Q_stricmp(level.mapname, "kejim_post") && ent->targetname && !Q_stricmp(ent->targetname, "jan")) { + // Bump up Jan's max health a little - give her random health for her too, with higher base pool it will be more leniant + if (cg_enableRandomizerEnhancements.integer && cg_bonusJanHealth.integer && !Q_stricmp(level.mapname, "kejim_post") && ent->targetname && !Q_stricmp(ent->targetname, "jan")) { ent->max_health += 50; } - else if (cg_enableRandomizer.integer) // Encapsulate max hp changes + if (cg_enableRandomizer.integer) // Encapsulate max hp changes { if (ent->max_health) { uniform_real_distribution NPC_HP_Dist(25, 400); diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index e623ae96..f5e44459 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -17,6 +17,7 @@ extern vmCvar_t cg_thirdPersonAlpha; // Posto / Randomizer : for the first weapon (It might roll a stun baton again, would be pretty funny) extern int GetRandomizedWeapon(); extern vmCvar_t cg_enableRandomizer; +extern vmCvar_t cg_enableRandomizerEnhancements; extern vmCvar_t cg_startWithPush; // g_client.c -- client functions that don't happen every frame @@ -737,7 +738,7 @@ void Player_RestoreFromPrevLevel(gentity_t *ent, SavedGameJustLoaded_e eSaveGame //On resetting by loading auto_kejim_post if (cg_enableRandomizer.integer && eSaveGameJustLoaded == eRESET) { //If start with push enabled then apply - have to handle it here so it applies without having to go to menu - if (cg_startWithPush.integer) { + if (cg_enableRandomizerEnhancements.integer && cg_startWithPush.integer) { client->ps.forcePowerLevel[FP_PUSH] = 1; client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (1 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); client->ps.forcePower = FORCE_POWER_MAX; diff --git a/code/game/wp_saber.cpp b/code/game/wp_saber.cpp index 6581b1ff..f11d5be7 100644 --- a/code/game/wp_saber.cpp +++ b/code/game/wp_saber.cpp @@ -8724,7 +8724,7 @@ void WP_InitForcePowers( gentity_t *ent ) ent->client->ps.forcePowerLevel[i] = 0; } //If using easy start, apply force push - if (cg_startWithPush.integer && !Q_stricmp(level.mapname, "kejim_post")) { + if (cg_enableRandomizerEnhancements.integer && cg_startWithPush.integer && !Q_stricmp(level.mapname, "kejim_post")) { ent->client->ps.forcePowersKnown = (0 << FP_HEAL) | (0 << FP_LEVITATION) | (0 << FP_SPEED) | (1 << FP_PUSH) | (0 << FP_PULL) | (0 << FP_TELEPATHY) | (0 << FP_GRIP) | (0 << FP_LIGHTNING) | (0 << FP_SABERTHROW) | (0 << FP_SABER_DEFENSE) | (0 << FP_SABER_OFFENSE); ent->client->ps.forcePowerLevel[FP_PUSH] = 1; ent->client->ps.forcePower = FORCE_POWER_MAX; From 00e283110aee3068b6957e25ba3c7598cc0f5d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Sun, 19 Jan 2025 15:38:34 +0100 Subject: [PATCH 59/62] Hotfix for NPC Jailer and Warden on both detention map. --- code/game/NPC_spawn.cpp | 8 ++++---- code/win32/AutoVersion.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code/game/NPC_spawn.cpp b/code/game/NPC_spawn.cpp index 3584d382..d8516d54 100644 --- a/code/game/NPC_spawn.cpp +++ b/code/game/NPC_spawn.cpp @@ -4043,9 +4043,9 @@ void SP_NPC_Imperial_Random(gentity_t* self) CheckIfMapChanged(); if (strcmp(lastKnownMap, "artus_detention") == 0) // The warden that we have hostage { - if (self->targetname) + if (self->NPC_targetname) { - if (!strcmp(self->targetname, "warden")) + if (!strcmp(self->NPC_targetname, "warden")) { SP_NPC_Spawn_Random_Humanoid(self); return; @@ -4065,9 +4065,9 @@ void SP_NPC_Imperial_Random(gentity_t* self) } if (strcmp(lastKnownMap, "doom_detention") == 0) // The jailer of Jan { - if (self->targetname) + if (self->NPC_targetname) { - if (!strcmp(self->targetname, "jailer")) + if (!strcmp(self->NPC_targetname, "jailer")) { SP_NPC_Spawn_Random_Humanoid(self); return; diff --git a/code/win32/AutoVersion.h b/code/win32/AutoVersion.h index 34840dbc..0b52b43a 100644 --- a/code/win32/AutoVersion.h +++ b/code/win32/AutoVersion.h @@ -3,10 +3,10 @@ #define VERSION_MAJOR_RELEASE 1 #define VERSION_MINOR_RELEASE 2 -#define VERSION_EXTERNAL_BUILD 0 +#define VERSION_EXTERNAL_BUILD 1 #define VERSION_INTERNAL_BUILD 0 -#define VERSION_STRING "1, 2, 0, 0" -#define VERSION_STRING_DOTTED "1.2.0.0" +#define VERSION_STRING "1, 2, 1, 0" +#define VERSION_STRING_DOTTED "1.2.1.0" #endif // __AUTO_VERSION_HEADER From 452a682265b067ea6896b9c0e354d00a3cf12b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Thu, 13 Feb 2025 09:43:51 +0100 Subject: [PATCH 60/62] Max HP changes. (#25) * Moved NPC max health into the enhancements and preparing Kyle/player max HP changes. * Updated the README.md and the UI in the .pk3 file. * Properly implementing information holder for Kyle's max health between missions. * Using the good rng engine for enhancements. --- README.md | 13 +++++- assets/assets_randomizer.pk3 | Bin 70985 -> 71146 bytes assets/ui/ingamerandomizer.menu | 64 ++++++++++++++++++++++++++++- assets/ui/randomizer.menu | 64 ++++++++++++++++++++++++++++- code/cgame/cg_main.cpp | 7 ++++ code/game/NPC_spawn.cpp | 10 +++-- code/game/g_client.cpp | 69 +++++++++++++++++++++++++++++--- code/win32/winquake.res | Bin 5480 -> 5480 bytes 8 files changed, 213 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 365570e1..74aa917d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Based on the source port of Star Wars Jedi Knight II: Jedi Outcast named SpeedOu #### `cg_enableRandomizer` (0 or 1) Enable or disable the NPC and items randomizer. +Only this was designed to be predictable. Default: `0`. #### `cg_enableRandomizerEnhancements` (0 or 1) @@ -22,6 +23,7 @@ Default: `0`. Enable or disable the other more 'exotic' randomized elements in the game. Check `List of addition for the 'exotic' Randomizer` below for more details. Need `cg_enableRandomizer` to be 1 to work. +This was not designed to be predictable but doesn't interfere with the RNG used in the 'base' randomizer. Default: `0`. #### `cg_setSeed` 10 digits string @@ -103,10 +105,17 @@ Prevents starting two enemies from attacking unless provoked. Start game with force push 1. #### `cg_bonusJanHealth` (0 or 1) -Applies a flat +50 to Jan's health on kejim_post. +Applies a flat +50 to Jan's health on kejim_post. This applies before random NPC health. +#### `cg_enableRandNPCHealth` (0 or 1) +Random health for NPCs. Range of 25% to 400%. -#### Todos +#### `cg_enableRandKyleHealth` (0 or 1) +Random health for Kyle as the player. Range of 33% to 300%. + + +### Todos +- Get approved for a possible speedrun randomizer leaderboard - Random codes for doom_comm (if possible) - Random codes for kejim_post (if possible) diff --git a/assets/assets_randomizer.pk3 b/assets/assets_randomizer.pk3 index f859ba40b5f0591cc6d58d26fe9aadd43819c53c..9cf13aa1e406475876c3930c88298e9e05cd47de 100644 GIT binary patch delta 10647 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 delta 10522 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 && !Q_stricmp(ent->targetname, "jan")) { + if (cg_enableRandomizer.integer && cg_enableRandomizerEnhancements.integer && cg_bonusJanHealth.integer && !Q_stricmp(level.mapname, "kejim_post") && ent->targetname && !Q_stricmp(ent->targetname, "jan")) { ent->max_health += 50; } - if (cg_enableRandomizer.integer) // Encapsulate max hp changes + if (cg_enableRandomizer.integer && cg_enableRandomizerEnhancements.integer && cg_enableRandNpcHealth.integer) // Encapsulate max hp changes { if (ent->max_health) { uniform_real_distribution NPC_HP_Dist(25, 400); - float rng = NPC_HP_Dist(rngRandoBase) / 100; //Get a multiplier value between 0.25 and 4 + float rng = NPC_HP_Dist(rngRandoEnhancements) / 100; //Get a multiplier value between 0.25 and 4 ent->max_health = (int)((float)ent->max_health * rng); //Result gets rounded when converted back to int so nothing explodes } } if (cg_enableRandomizer.integer && cg_enableRandomizerEnhancements.integer && cg_enableRandNPCSpeed.integer) { uniform_real_distribution NPC_Speed_Dist(33, 300); - float rng = NPC_Speed_Dist(rngRandoBase) / 100; //Get a multiplier value between 0.33 and 3 + float rng = NPC_Speed_Dist(rngRandoEnhancements) / 100; //Get a multiplier value between 0.33 and 3 ent->NPC->stats.runSpeed = (int)((float)ent->NPC->stats.runSpeed * rng); ent->NPC->stats.walkSpeed = (int)((float)ent->NPC->stats.walkSpeed * rng); ent->NPC->stats.yawSpeed = (int)((float)ent->NPC->stats.yawSpeed * rng); diff --git a/code/game/g_client.cpp b/code/game/g_client.cpp index f5e44459..cb9ff436 100644 --- a/code/game/g_client.cpp +++ b/code/game/g_client.cpp @@ -14,11 +14,16 @@ extern void G_CreateG2AttachedWeaponModel( gentity_t *ent, const char *weaponMod extern qboolean CheatsOk( gentity_t *ent ); extern vmCvar_t cg_thirdPersonAlpha; -// Posto / Randomizer : for the first weapon (It might roll a stun baton again, would be pretty funny) +// Randomizer +#include extern int GetRandomizedWeapon(); extern vmCvar_t cg_enableRandomizer; extern vmCvar_t cg_enableRandomizerEnhancements; extern vmCvar_t cg_startWithPush; +extern vmCvar_t cg_enableRandKyleHealth; +extern mt19937 rngRandoEnhancements; +extern SavedGameJustLoaded_e g_eSavedGameJustLoaded; +extern vmCvar_t memorized_kyle_health; // g_client.c -- client functions that don't happen every frame @@ -439,11 +444,43 @@ void ClientUserinfoChanged( int clientNum ) { } } - // set max health - client->pers.maxHealth = atoi( Info_ValueForKey( userinfo, "handicap" ) ); - if ( client->pers.maxHealth < 1 || client->pers.maxHealth > 100 ) { - client->pers.maxHealth = 100; + // Randomizer : max health changes for Kyle / player + if (cg_enableRandomizer.integer && cg_enableRandomizerEnhancements.integer && cg_enableRandKyleHealth.integer) + { + // Set it only during kejim_post, eNo and eReset are valid + if (!strcmp(level.mapname, "kejim_post") && (g_eSavedGameJustLoaded == eNO || g_eSavedGameJustLoaded == eRESET)) + { + int base_health = 100; + uniform_real_distribution NPC_Speed_Dist(33, 300); + float rng = NPC_Speed_Dist(rngRandoEnhancements) / 100; //Get a multiplier value between 0.33 and 3 + client->pers.maxHealth = (int)((float)base_health * rng); + ent->max_health = client->pers.maxHealth; + memorized_kyle_health.integer = client->pers.maxHealth; + memorized_kyle_health.value = client->pers.maxHealth; + string buffer = to_string(client->pers.maxHealth); + for (int i = 0 ; i < buffer.size() ; i++) + { + memorized_kyle_health.string[i] = buffer[i]; + } + memorized_kyle_health.string[buffer.size()] = '\0'; + memorized_kyle_health.modificationCount++; + extern void cgi_Cvar_Set(const char* var_name, const char* value); + cgi_Cvar_Set("memorized_kyle_health", memorized_kyle_health.string); + } + else + { + client->pers.maxHealth = memorized_kyle_health.integer; + } + } + else // Normal game, non randomizer + { + // set max health + client->pers.maxHealth = atoi(Info_ValueForKey(userinfo, "handicap")); + if (client->pers.maxHealth < 1 || client->pers.maxHealth > 100) { + client->pers.maxHealth = 100; + } } + client->ps.stats[STAT_MAX_HEALTH] = client->pers.maxHealth; // sounds @@ -685,7 +722,27 @@ void Player_RestoreFromPrevLevel(gentity_t *ent, SavedGameJustLoaded_e eSaveGame &client->ps.saberLockEnemy, &client->ps.saberLockTime ); - ent->health = client->ps.stats[STAT_HEALTH]; + // Randomizer : max health changes for Kyle / player + if (cg_enableRandomizer.integer && cg_enableRandomizerEnhancements.integer && cg_enableRandKyleHealth.integer) + { + // Set it only during kejim_post, eNo and eReset are valid + // If you do a eReset during post, for some reason maxhealth is not cleared properly + if (!strcmp(level.mapname, "kejim_post") && (g_eSavedGameJustLoaded == eNO || g_eSavedGameJustLoaded == eRESET)) + { + ent->max_health = client->ps.stats[STAT_MAX_HEALTH]; + client->pers.maxHealth = client->ps.stats[STAT_MAX_HEALTH]; + } + else // We good, it's not a reset in kejim_post + { + ent->health = client->ps.stats[STAT_HEALTH]; + } + + } // Base game + else + { + ent->health = client->ps.stats[STAT_HEALTH]; + } + // slight issue with ths for the moment in that although it'll correctly restore angles it doesn't take into account // the overall map orientation, so (eg) exiting east to enter south will be out by 90 degrees, best keep spawn angles for now diff --git a/code/win32/winquake.res b/code/win32/winquake.res index 6f58d2668518e50cff2b2f6aabe506a61fe6ff07..39cc75623a4a2c8876e3948c36e3e3cfd1662365 100644 GIT binary patch delta 53 ucmaE%^+Icdgb+Uy10w?i5JTzB>O%dD>_!Ya3F1`Ik33JeCD_X>x?Ig=$t{Q>)B2-^Sv From 7157689d80090e8f0566b1360b3d1c9740afc4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= Date: Thu, 13 Feb 2025 09:51:13 +0100 Subject: [PATCH 61/62] Switching to version 1.3 --- code/win32/AutoVersion.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/code/win32/AutoVersion.h b/code/win32/AutoVersion.h index 0b52b43a..c1a6abc8 100644 --- a/code/win32/AutoVersion.h +++ b/code/win32/AutoVersion.h @@ -2,11 +2,11 @@ #define __AUTO_VERSION_HEADER #define VERSION_MAJOR_RELEASE 1 -#define VERSION_MINOR_RELEASE 2 -#define VERSION_EXTERNAL_BUILD 1 +#define VERSION_MINOR_RELEASE 3 +#define VERSION_EXTERNAL_BUILD 0 #define VERSION_INTERNAL_BUILD 0 -#define VERSION_STRING "1, 2, 1, 0" -#define VERSION_STRING_DOTTED "1.2.1.0" +#define VERSION_STRING "1, 3, 0, 0" +#define VERSION_STRING_DOTTED "1.3.0.0" #endif // __AUTO_VERSION_HEADER From d6f336f2b51711e954bd3b90fc5a397ea85667b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Gon=C3=A7alves?= <81418700+ArrayIndexOutOfBound@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:41:34 +0200 Subject: [PATCH 62/62] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 74aa917d..b3d79f99 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,15 @@ Default: `0`. Draw the seed used during a run. Will draw "No Rand" is `cg_enableRandomizer` is 0. Default: `0`. +## About Force Holocrons +Holocron items, like the one you can find on the map yavin_trial, are available as collectible items. +Here are how they work : +- When an holocron is rolled during the randomized process, they only have a 33% to 'stay'. If you hit the 66% remaining, the item will be rerolled. +- They have a slightly higher hitbox, so they may be picked from a bit father than what their 3D model indicate. +- When picked up, if you didn't had the force power, you will unlock it and a "New Force Power" popup will appear. +- When picked up, if you already had a force power, it will be incremented by 1. +- When pickup up, if you already had this specific force power at level 3, nothing will happen. You also won't see the "New Force Power" popup. +- The Force powers will still increment as they should between missions. ## List of addition for the base Randomizer