]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Add spawning random props in the map, prop model random assignment for runners, still...
authorLegendaryGuard <rootuser999@gmail.com>
Sat, 25 Dec 2021 00:30:07 +0000 (01:30 +0100)
committerLegendaryGuard <rootuser999@gmail.com>
Sat, 25 Dec 2021 00:30:07 +0000 (01:30 +0100)
gamemodes-server.cfg
qcsrc/common/gamemodes/gamemode/mh/sv_mh.qc
qcsrc/common/gamemodes/gamemode/mh/sv_mh.qh

index 7e45c4086c62fce179bf274b81d6c3d4f98503d0..b849e411c49ce62cbefd20a154047ab2d32b80cb 100644 (file)
@@ -576,16 +576,20 @@ set g_mh 0 "Manhunt: Hunters go in search of the runners"
 set g_mh_not_dm_maps 0 "when this is set, DM maps will NOT be listed in MH"
 set g_mh_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
 set g_mh_point_limit -1 "MH point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-set g_mh_warmup 10 //10 "time players get to run around before the round starts"
-set g_mh_round_timelimit 120 //180 "round time limit in seconds"
+set g_mh_warmup 10 "time players get to run around before the round starts" //10 
+set g_mh_round_timelimit 120  "round time limit in seconds" //180
 set g_mh_how_many_rounds_before_shuffle 1 "how many rounds are played before teams are shuffled automatically"
 set g_mh_enable_tagging_on_touch 1 "are runners killed when touching hunters?"
 set g_mh_player_waypoints 1 "0: no waypoints, 1: waypoints on runners, 2: waypoints on everyone"
 set g_mh_weaponarena " " "starting weapons - takes the same options as g_weaponarena"
-set g_mh_weapons_damage 0 "0: no damage, 1: only self-damage for runners, 2: only damage opposing team, 3: only allow hunters to damage runners, 4: self-damage and opposing team damage"
+set g_mh_weapons_damage 3 "0: no damage, 1: only self-damage for runners, 2: only damage opposing team, 3: only allow hunters to damage runners, 4: self-damage and opposing team damage"
 set g_mh_weapons_force 1 "0: no force, 1: only self-force, 2: self-force and opposing team force"
 set g_mh_limited_ammunition 0 "do players consume ammunition when firing"
 set g_mh_hunterblind 1 "when this is set, hunters can't see anything until the round starts"
 set g_mh_autotaunt_runner 1 "when this is set, runners play automatically a sound being noticed by everyone"
 set g_mh_autotaunt_runner_time 35 "runner automatic taunt time, plays a sound automatically when time is over, and restarts taunt time"
-set g_mh_propmode 1 "when this is set, runners are spawned as props"
\ No newline at end of file
+set g_mh_propmode 1 "when this is set, runners are spawned as props"
+set g_mh_random_props_count 30 "props are spawned randomly around map"
+set g_mh_random_props_tries 20 "Try to place a prop this many times before giving up"
+set g_mh_random_props_droptofloor 0 "Drop the props instantly so they don't appear to fall from the sky"
+set g_mh_random_props_droptofloor_maxdepth -1 "Maximum depth for the trace in props (use negative value for the map size)"
\ No newline at end of file
index d6dcc7c47a13a45e62053117459549242f958609..3ad7c309e07bf7308ce84ebaf05c9671d36799c6 100644 (file)
@@ -5,6 +5,11 @@
 .vector taggedplayervelocity;
 .vector taggedplayerviewangles;
 .float RunnerSoundTaunt_time;
+.entity mh_prop; // TODO: to be checked
+.bool modelchecked;
+.entity original;
+
+bool first_time_props_spawn;
 
 void MH_FakeTimeLimit(entity e, float t)
 {
@@ -23,6 +28,73 @@ void MH_FakeTimeLimit(entity e, float t)
 #endif
 }
 
+void prop_think(entity this)
+{
+       this.nextthink = time + 0.15; // don't need to update often, very unlikely for these to move
+       CSQCMODEL_AUTOUPDATE(this);
+}
+
+void PropSetup(entity ent)
+{
+       setmodel(ent, MDL_RUNNER_PROP_RANDOM());
+       setsize(ent, '-16 -16 -16', '16 16 16'); //ent.mins, ent.maxs);
+       setthink(ent, prop_think);
+       ent.nextthink = time + 0.25;
+       CSQCMODEL_AUTOINIT(ent);
+
+       if(!ent.bot_attack)
+               IL_PUSH(g_bot_targets, ent);
+       ent.bot_attack = true;
+       
+       //ent.pickup_anyway = true;
+       ent.scale = 1.4;
+       ent.angles_y = floor(random() * 180);
+       //ent.takedamage = DAMAGE_AIM;
+       //SetResourceExplicit(ent, RES_HEALTH, 100);
+
+       ent.solid = SOLID_BBOX;
+       ent.mass = 5;
+       ent.bouncefactor = 0.2;
+       ent.bouncestop = 0.3;
+       ent.friction = 1;
+       set_movetype(ent, MOVETYPE_STEP); //test with MOVETYPE_TOSS or MOVETYPE_WALK (it's like sliding object) or MOVETYPE_BOUNCE (maybe not good)
+       //setorigin(ent, org);
+       ent.velocity = randomvec() * 150 + '0 0 325';
+       ent.reset = SUB_Remove;
+       
+       ent.mh_prop.model = ent.model; // assigns prop model if this is the case when runners shot it
+}
+
+void prop_droptofloor(entity e)
+{
+       float max_depth = ((autocvar_g_mh_random_props_droptofloor_maxdepth < 0) ? max_shot_distance : autocvar_g_mh_random_props_droptofloor_maxdepth);
+       tracebox(e.origin, e.mins, e.maxs, e.origin - ('0 0 1' * max_depth), MOVE_NORMAL, e);
+       setorigin(e, trace_endpos);
+}
+
+void SpawnProps(int pcount)
+{
+       pcount = autocvar_g_mh_random_props_count;
+       for(int j = 0; j < pcount; ++j)
+       {
+               entity e = spawn();
+               if(MoveToRandomMapLocation(e, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, autocvar_g_mh_random_props_tries, 1024, 256))
+               {
+                       if(autocvar_g_mh_random_props_droptofloor)
+                               droptofloor(e);
+                       else
+                               prop_droptofloor(e);
+
+                       e.angles = '0 0 0';
+                       e.gravity = 1;
+                       e.spawnfunc_checked = true;
+                       PropSetup(e);
+               }
+               else
+                       delete(e); // removes entity
+       }
+}
+
 MUTATOR_HOOKFUNCTION(mh, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(1, string) = "mh_team";
@@ -35,8 +107,7 @@ MUTATOR_HOOKFUNCTION(mh, Scores_CountFragsRemaining)
 }
 
 // Prop feature
-.entity mh_prop; // TODO: to be checked
-.bool modelchecked;
+
 MUTATOR_HOOKFUNCTION(mh, FixPlayermodel)
 {
        entity player = M_ARGV(2, entity);
@@ -47,14 +118,22 @@ MUTATOR_HOOKFUNCTION(mh, FixPlayermodel)
                {
                        //string defaultmodel = M_ARGV(0, string);
                        // TODO: to be checked
-                       if (!player.mh_prop.modelchecked)
+                       if (!IS_DEAD(player) && !player.mh_prop.modelchecked) // to brake the loop
                        {
-                               //PrintToChatAll("PROPMODEL CHECKED");
+                               player.original.model = player.model;
+                               player.original.skin = player.skin;
+
                                player.mh_prop.model = MDL_RUNNER_PROP_RANDOM().model_str();
+
+                               player.mh_prop.solid = SOLID_BBOX;
+                               setsize(player, '-16 -16 -16', '16 16 16');
+
                                M_ARGV(0, string) = player.mh_prop.model;
                                M_ARGV(1, int) = player.mh_prop.skin;
-                               player.playermodel = M_ARGV(0,string);
+
                                //setmodel(player, MDL_RUNNER_PROP_RANDOM());
+                               player.playermodel = M_ARGV(0, string);
+
                                player.mh_prop.modelchecked = true;
                        }
                        
@@ -77,7 +156,7 @@ MUTATOR_HOOKFUNCTION(mh, PlayerPreThink)
 {
        entity player = M_ARGV(0, entity);
 
-       if(autocvar_g_mh_enable_tagging_on_touch && round_handler_IsRoundStarted() && player.team == Team_IndexToTeam(1) && !game_stopped && !IS_DEAD(player) && IS_PLAYER(player) && !IS_INDEPENDENT_PLAYER(player))
+       if(!autocvar_g_mh_propmode && autocvar_g_mh_enable_tagging_on_touch && round_handler_IsRoundStarted() && player.team == Team_IndexToTeam(1) && !game_stopped && !IS_DEAD(player) && IS_PLAYER(player) && !IS_INDEPENDENT_PLAYER(player))
        {
                FOREACH_CLIENT(IS_PLAYER(it) && it != player && it.team == Team_IndexToTeam(2), {
                        if(!IS_DEAD(it) && !IS_INDEPENDENT_PLAYER(it))
@@ -114,7 +193,7 @@ MUTATOR_HOOKFUNCTION(mh, PlayerPreThink)
                        MOVE_NORMAL, 
                        player, 
                        ANTILAG_LATENCY(player)
-               );*/
+               ); crosshair_trace(player);*/
        
        // Autotaunt feature
        if(autocvar_g_mh_autotaunt_runner)
@@ -643,11 +722,26 @@ MUTATOR_HOOKFUNCTION(mh, PutClientInServer)
 {
        entity player = M_ARGV(0, entity);
        
+       // if it's the first time that starts the gamemode for the props
+       if (autocvar_g_mh_propmode)
+       {
+               if (!first_time_props_spawn)
+               {
+                       SpawnProps(autocvar_g_mh_random_props_count);
+                       first_time_props_spawn = true;
+               }
+       }
+       
        if (!allowed_to_spawn_untagged && IS_PLAYER(player) && round_handler_IsRoundStarted()){ // this can be true even when player is trying to join
                if (CS(player).jointime != time){ // not when connecting
                        MH_FakeTimeLimit(player, round_handler_GetEndTime() - CS(player).jointime); // set HUD with current round time
                        Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_MH_JOIN_LATE);
                }
+
+               // if(player.mh_prop) // TOFIX: only spawns per one and not for all
+               //player.mh_prop = player;
+               /*if (player.team == Team_IndexToTeam(2))
+                       player.mh_prop.modelchecked = false;*/
        }
 }
 
@@ -683,6 +777,12 @@ MUTATOR_HOOKFUNCTION(mh, PlayerDies)
 
        if (frag_target.waypointsprite_attachedforcarrier)
                WaypointSprite_Kill(frag_target.waypointsprite_attachedforcarrier);
+       
+       /*if (IS_DEAD(frag_target) && frag_target.playermodel == frag_target.mh_prop.model) // return player original model to avoid spamming errors
+       {
+               frag_target.skin = frag_target.original.skin;
+               frag_target.playermodel = frag_target.original.model;
+       }*/
 
        mh_LastPlayerForTeam_Notify(frag_target);
        if (!allowed_to_spawn_untagged)
@@ -725,7 +825,7 @@ MUTATOR_HOOKFUNCTION(mh, PlayerSpawn)
        entity player = M_ARGV(0, entity);
        player.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
        MH_count_players();
-       
+
        if(autocvar_g_mh_hunterblind)
        {
                if(player.team == Team_IndexToTeam(1))
@@ -734,15 +834,24 @@ MUTATOR_HOOKFUNCTION(mh, PlayerSpawn)
 
        if(autocvar_g_mh_propmode)
        {
+               if(player.team == Team_IndexToTeam(1)) // Hunter needs weapons
+               {
+                       //GiveWeapon(player, WEP_BLASTER.m_id, OP_PLUS, 1);
+                       GiveWeapon(player, WEP_SHOTGUN.m_id, OP_PLUS, 1);
+                       GiveWeapon(player, WEP_SHOCKWAVE.m_id, OP_PLUS, 1);
+                       GiveWeapon(player, WEP_MACHINEGUN.m_id, OP_PLUS, 1);
+                       GiveWeapon(player, WEP_MORTAR.m_id, OP_PLUS, 1);
+               }
+
                if(player.team == Team_IndexToTeam(2) && !IS_DEAD(player))
                {
                        //setmodel(player, MDL_RUNNER_PROP2);
                        //setplayermodel(player, MDL_RUNNER_PROP_RANDOM().model_str());//prop_setup(player);
                        //setmodel(player, MDL_RUNNER_PROP_RANDOM());
                        LOG_INFOF("Spawned prop");
-                       
-                       if(player.mh_prop) // TOFIX: only spawns per one and not for all
-                               player.mh_prop.modelchecked = false;
+                       //player.mh_prop.model = MDL_RUNNER_PROP_RANDOM().model_str();
+                       //player.playermodel = player.mh_prop.model;
+                       player.mh_prop.modelchecked = false;
                }
        }
        
@@ -777,6 +886,9 @@ MUTATOR_HOOKFUNCTION(mh, PlayerSpawn)
 //reset kill streaks and respawn players on round reset
 MUTATOR_HOOKFUNCTION(mh, reset_map_players)
 {
+       if (autocvar_g_mh_propmode)
+               SpawnProps(autocvar_g_mh_random_props_count);
+       
        FOREACH_CLIENT(true, {
                CS(it).killcount = 0;
                MH_FakeTimeLimit(it, -1);
@@ -798,8 +910,6 @@ MUTATOR_HOOKFUNCTION(mh, reset_map_players)
 //  to change
 // ===========
 
-
-
 //idk if this function is needed
 MUTATOR_HOOKFUNCTION(mh, reset_map_global)
 {
index ed4021b46fa3e7d5f733abe2d4c1b01395078fa9..d7594c5601ec00ff10358f7c5bd00a181d23249b 100644 (file)
@@ -18,6 +18,10 @@ bool autocvar_g_mh_hunterblind;
 bool autocvar_g_mh_propmode;
 bool autocvar_g_mh_autotaunt_runner;
 float autocvar_g_mh_autotaunt_runner_time;
+int autocvar_g_mh_random_props_count;
+int autocvar_g_mh_random_props_tries;
+bool autocvar_g_mh_random_props_droptofloor;
+float autocvar_g_mh_random_props_droptofloor_maxdepth;
 
 int mh_teams;
 bool allowed_to_spawn_untagged = 1;