]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/gamemodes/gamemode/tmayhem/sv_tmayhem.qc
acb10404e90fb35040ebb6cc17e18fc242c762aa
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / gamemodes / gamemode / tmayhem / sv_tmayhem.qc
1 #include "sv_tmayhem.qh"
2
3 // TODO? rename to teammayhem? requires checking alias length
4 int autocvar_g_tmayhem_teams;
5 int autocvar_g_tmayhem_teams_override;
6
7 bool autocvar_g_tmayhem_regenerate;
8 string autocvar_g_tmayhem_weaponarena;
9 bool autocvar_g_tmayhem_powerups;
10 bool autocvar_g_tmayhem_selfdamage;
11 int autocvar_g_tmayhem_scoringmethod;
12
13
14
15 // code from here on is just to support maps that don't have team entities
16 void tmayhem_SpawnTeam (string teamname, int teamcolor)
17 {
18         entity this = new_pure(tmayhem_team);
19         this.netname = teamname;
20         this.cnt = teamcolor - 1;
21         this.team = teamcolor;
22         this.spawnfunc_checked = true;
23         //spawnfunc_tmayhem_team(this);
24 }
25
26 void tmayhem_DelayedInit(entity this)
27 {
28         // if no teams are found, spawn defaults
29         if(find(NULL, classname, "tmayhem_team") == NULL)
30         {
31                 LOG_TRACE("No \"tmayhem_team\" entities found on this map, creating them anyway.");
32
33                 int numteams = autocvar_g_tmayhem_teams_override;
34                 if(numteams < 2) { numteams = autocvar_g_tmayhem_teams; }
35
36                 int teams = BITS(bound(2, numteams, 4));
37                 if(teams & BIT(0))
38                         tmayhem_SpawnTeam("Red", NUM_TEAM_1);
39                 if(teams & BIT(1))
40                         tmayhem_SpawnTeam("Blue", NUM_TEAM_2);
41                 if(teams & BIT(2))
42                         tmayhem_SpawnTeam("Yellow", NUM_TEAM_3);
43                 if(teams & BIT(3))
44                         tmayhem_SpawnTeam("Pink", NUM_TEAM_4);
45         }
46 }
47
48 void tmayhem_Initialize()
49 {
50         if(autocvar_g_tmayhem_visual_score_limit != 0 && autocvar_g_tmayhem_fraglimit != 0)
51                 tmayhempointmultiplier = autocvar_g_tmayhem_visual_score_limit / autocvar_g_tmayhem_fraglimit;
52
53         GameRules_teams(true);
54         GameRules_spawning_teams(autocvar_g_tmayhem_team_spawns);
55         GameRules_limit_score(autocvar_g_tmayhem_visual_score_limit);
56         GameRules_limit_lead(autocvar_g_tmayhem_score_leadlimit);
57
58         InitializeEntity(NULL, tmayhem_DelayedInit, INITPRIO_GAMETYPE);
59 }
60
61 MUTATOR_HOOKFUNCTION(tmayhem, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
62 {
63         M_ARGV(1, string) = "tmayhem_team";
64 }
65
66 MUTATOR_HOOKFUNCTION(tmayhem, Scores_CountFragsRemaining)
67 {
68         // announce remaining frags
69         return true;
70 }
71
72 MUTATOR_HOOKFUNCTION(tmayhem, SetStartItems)
73 {
74         start_items       &= ~(IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS);
75         start_health       = warmup_start_health       = cvar("g_tmayhem_start_health");
76         start_armorvalue   = warmup_start_armorvalue   = cvar("g_tmayhem_start_armor");
77         start_ammo_shells  = warmup_start_ammo_shells  = cvar("g_tmayhem_start_ammo_shells");
78         start_ammo_nails   = warmup_start_ammo_nails   = cvar("g_tmayhem_start_ammo_nails");
79         start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_tmayhem_start_ammo_rockets");
80         start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_tmayhem_start_ammo_cells");
81         start_ammo_plasma  = warmup_start_ammo_plasma  = cvar("g_tmayhem_start_ammo_plasma");
82         start_ammo_fuel    = warmup_start_ammo_fuel    = cvar("g_tmayhem_start_ammo_fuel");
83 }
84
85 //this hook also enables rotting, as players spawn with more hp and armor than what default rot limits are set to this is a bad idea as of now
86 MUTATOR_HOOKFUNCTION(tmayhem, PlayerRegen)
87 {
88         if(autocvar_g_tmayhem_regenerate)
89                 return false;
90         return true;
91 }
92
93 MUTATOR_HOOKFUNCTION(tmayhem, ForbidThrowCurrentWeapon)
94 {
95         return true;
96 }
97
98 MUTATOR_HOOKFUNCTION(tmayhem, SetWeaponArena)
99 {
100         if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "")
101                 M_ARGV(0, string) = autocvar_g_tmayhem_weaponarena;
102 }
103
104 MUTATOR_HOOKFUNCTION(tmayhem, FilterItem)
105 {
106         entity item = M_ARGV(0, entity);
107         if (autocvar_g_powerups == 1){
108                 if (item.flags & FL_POWERUP){
109                         return false;
110                 } 
111         }
112         else if (autocvar_g_powerups == -1){
113                 if (item.flags & FL_POWERUP){
114                         if (autocvar_g_tmayhem_powerups){
115                                 return false;
116                         } 
117                 } 
118         }
119         if (autocvar_g_pickup_items <= 0)
120                 return true;
121 }
122
123 MUTATOR_HOOKFUNCTION(tmayhem, Damage_Calculate)
124 {
125         entity frag_attacker = M_ARGV(1, entity);
126         entity frag_target = M_ARGV(2, entity);
127         float frag_deathtype = M_ARGV(3, float);
128         float frag_damage = M_ARGV(4, float);
129         float frag_mirrordamage = M_ARGV(5, float);
130
131         if (IS_PLAYER(frag_target))
132         if (!IS_DEAD(frag_target))
133         if ((autocvar_g_tmayhem_selfdamage == 0 && frag_target == frag_attacker) || frag_deathtype == DEATH_FALL.m_id)
134                 frag_damage = 0;
135
136         frag_mirrordamage = 0;
137
138         M_ARGV(4, float) = frag_damage;
139         M_ARGV(5, float) = frag_mirrordamage;
140 }
141
142 MUTATOR_HOOKFUNCTION(tmayhem, PlayerDamage_SplitHealthArmor)
143 {
144         switch(autocvar_g_tmayhem_scoringmethod)
145         {
146                 //frags only
147                 case 2:
148                 {
149                         return;
150                 }
151                 
152                 //damage only
153                 case 3:
154                 {
155                         entity frag_attacker = M_ARGV(1, entity);
156                         entity frag_target = M_ARGV(2, entity);
157                         float frag_deathtype = M_ARGV(6, float);
158                         float frag_damage = M_ARGV(7, float);
159                         float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH));
160                         float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR));
161
162                         float excess = max(0, frag_damage - damage_take - damage_save);
163
164                         if (frag_target != frag_attacker && IS_PLAYER(frag_attacker))
165                                 GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * (1/(start_health + start_armorvalue)));
166                         
167                         if (frag_target == frag_attacker && IS_PLAYER(frag_attacker))
168                                 GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * (1/(start_health + start_armorvalue)));
169                 
170                         //handle hazard suiciding, check first if player has a registered attacker who most likely pushed them there
171                         if (!IS_PLAYER(frag_attacker) && (
172                                 frag_deathtype == DEATH_DROWN.m_id ||
173                                 frag_deathtype == DEATH_HURTTRIGGER.m_id ||
174                                 frag_deathtype == DEATH_CAMP.m_id ||
175                                 frag_deathtype == DEATH_LAVA.m_id ||
176                                 frag_deathtype == DEATH_SLIME.m_id))
177                                         GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * (1/(start_health + start_armorvalue)));
178                                 
179                         //when hp and armor values are checked when suiciding for some reason they are 0.9 hp and 0 armor regardless that player suicided with 200+200
180                         //AFAIK dynamic hp value checking is not possible, hardcoded start hp and armor
181                         //FIXME: ^ , might require fixing hp+a check for suicides as a whole
182                         if (frag_deathtype == DEATH_KILL.m_id)
183                                 GameRules_scoring_add_team(frag_target, SCORE, (-1 * (start_health + start_armorvalue)) * (1/(start_health + start_armorvalue)));
184                         return;
185                 }
186                 
187                 //combined damage and frags
188                 default:
189                 case 1:
190                 {
191                         entity frag_attacker = M_ARGV(1, entity);
192                         entity frag_target = M_ARGV(2, entity);
193                         float frag_deathtype = M_ARGV(6, float);
194                         float frag_damage = M_ARGV(7, float);
195                         float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH));
196                         float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR));
197
198                         float excess = max(0, frag_damage - damage_take - damage_save);
199
200                         if (frag_target != frag_attacker && IS_PLAYER(frag_attacker))
201                                 GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * 0.75 * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
202                         
203                         if (frag_target == frag_attacker && IS_PLAYER(frag_attacker))
204                                 GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * 0.75 * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
205                 
206                         //handle hazard suiciding, check first if player has a registered attacker who most likely pushed them there
207                         if (!IS_PLAYER(frag_attacker) && (
208                                 frag_deathtype == DEATH_DROWN.m_id ||
209                                 frag_deathtype == DEATH_HURTTRIGGER.m_id ||
210                                 frag_deathtype == DEATH_CAMP.m_id ||
211                                 frag_deathtype == DEATH_LAVA.m_id ||
212                                 frag_deathtype == DEATH_SLIME.m_id))
213                                         GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * 0.75 * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
214                                 
215                         //when hp and armor values are checked when suiciding for some reason they are 0.9 hp and 0 armor regardless that player suicided with 200+200
216                         //AFAIK dynamic hp value checking is not possible, hardcoded start hp and armor
217                         //FIXME: ^ , might require fixing hp+a check for suicides as a whole
218                         if (frag_deathtype == DEATH_KILL.m_id)
219                                 GameRules_scoring_add_team(frag_target, SCORE, (-1 * (start_health + start_armorvalue)) * 0.75 * tmayhempointmultiplier * (1/(start_health + start_armorvalue)));
220                         return;
221                 }
222         }
223 }
224
225 MUTATOR_HOOKFUNCTION(tmayhem, GiveFragsForKill, CBC_ORDER_FIRST)
226 {
227         switch(autocvar_g_tmayhem_scoringmethod)
228         {
229                 //frags only
230                 case 2:
231                 {
232                                                                                                                 //fix 999 score from 30 kills for example
233                         M_ARGV(2, float) = 1 * tmayhempointmultiplier * 1.0001;
234                         return true;
235                 }
236                 
237                 //damage only
238                 case 3:
239                 {
240                         M_ARGV(2, float) = 0;
241                         return true;
242                 }
243                 
244                 //combined damage and frags
245                 default:
246                 case 1:
247                 {
248                         M_ARGV(2, float) = 0.25 * tmayhempointmultiplier * 1.0001;
249                         return true;
250                 }
251         }
252 }