]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/clientkill.qc
Tidy up classnames
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / clientkill.qc
1 #include "clientkill.qh"
2
3 #include <common/csqcmodel_settings.qh>
4 #include <common/deathtypes/all.qh>
5 #include <common/mapobjects/triggers.qh>
6 #include <common/notifications/all.qh>
7 #include <common/stats.qh>
8 #include <common/stats.qh>
9 #include <common/vehicles/sv_vehicles.qh>
10 #include <common/weapons/_all.qh>
11 #include <server/client.qh>
12 #include <server/damage.qh>
13 #include <server/mutators/_mod.qh>
14 #include <server/player.qh>
15 #include <server/teamplay.qh>
16
17 void ClientKill_Now_TeamChange(entity this)
18 {
19         if (this.killindicator_teamchange == -1)
20         {
21                 TeamBalance_JoinBestTeam(this);
22         }
23         else if (this.killindicator_teamchange == -2)
24         {
25                 if (blockSpectators)
26                         Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
27                 PutObserverInServer(this);
28         }
29         else
30         {
31                 Player_SetTeamIndexChecked(this, Team_TeamToIndex(
32                         this.killindicator_teamchange));
33         }
34         this.killindicator_teamchange = 0;
35 }
36
37 void ClientKill_Now(entity this)
38 {
39         if (this.vehicle)
40         {
41                 vehicles_exit(this.vehicle, VHEF_RELEASE);
42                 if (!this.killindicator_teamchange)
43                 {
44                         this.vehicle_health = -1;
45                         Damage(this, this, this, 1 , DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
46                 }
47         }
48
49         if (this.killindicator && !wasfreed(this.killindicator))
50                 delete(this.killindicator);
51
52         this.killindicator = NULL;
53
54         if (this.killindicator_teamchange)
55                 ClientKill_Now_TeamChange(this);
56
57         if (!IS_SPEC(this) && !IS_OBSERVER(this) && MUTATOR_CALLHOOK(ClientKill_Now, this) == false)
58         {
59                 Damage(this, this, this, 100000, DEATH_KILL.m_id, DMG_NOWEP, this.origin, '0 0 0');
60         }
61
62         // now I am sure the player IS dead
63 }
64 void KillIndicator_Think(entity this)
65 {
66         if (game_stopped || (this.owner.alpha < 0 && !this.owner.vehicle))
67         {
68                 this.owner.killindicator = NULL;
69                 delete(this);
70                 return;
71         }
72
73         if (this.cnt <= 0)
74         {
75                 ClientKill_Now(this.owner);
76                 return;
77         }
78
79         // count == 1 means that it's silent
80         if (this.count != 1)
81         {
82                 if (this.cnt <= 10)
83                         setmodel(this, MDL_NUM(this.cnt));
84                 if (IS_REAL_CLIENT(this.owner))
85                 {
86                         if (this.cnt <= 10)
87                                 Send_Notification(NOTIF_ONE, this.owner, MSG_ANNCE, Announcer_PickNumber(CNT_KILL, this.cnt));
88                 }
89         }
90         this.nextthink = time + 1;
91         this.cnt -= 1;
92 }
93
94 .float lip;
95 float clientkilltime;
96 .float clientkill_nexttime;
97 void ClientKill_TeamChange(entity this, float targetteam) // 0 = don't change, -1 = auto, -2 = spec
98 {
99         if (game_stopped)
100                 return;
101
102         float killtime = autocvar_g_balance_kill_delay;
103
104         if (MUTATOR_CALLHOOK(ClientKill, this, killtime))
105                 return;
106         killtime = M_ARGV(1, float);
107
108         this.killindicator_teamchange = targetteam;
109
110         // this.killindicator.count == 1 means that the kill indicator was spawned by ClientKill_Silent
111         if(killtime <= 0 && this.killindicator && this.killindicator.count == 1)
112         {
113                 ClientKill_Now(this); // allow instant kill in this case
114                 return;
115         }
116
117         if (!this.killindicator)
118         {
119                 if (!IS_DEAD(this))
120                 {
121                         killtime = max(killtime, this.clientkill_nexttime - time);
122                         this.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
123                 }
124
125                 if (killtime <= 0 || !IS_PLAYER(this) || IS_DEAD(this))
126                 {
127                         ClientKill_Now(this);
128                 }
129                 else
130                 {
131                         float starttime = max(time, clientkilltime);
132
133                         this.killindicator = new(killindicator);
134                         this.killindicator.owner = this;
135                         this.killindicator.scale = 0.5;
136                         setattachment(this.killindicator, this, "");
137                         setorigin(this.killindicator, '0 0 52');
138                         setthink(this.killindicator, KillIndicator_Think);
139                         this.killindicator.nextthink = starttime + (this.lip) * 0.05;
140                         clientkilltime = max(clientkilltime, this.killindicator.nextthink + 0.05);
141                         this.killindicator.cnt = ceil(killtime);
142                         this.killindicator.count = bound(0, ceil(killtime), 10);
143                         //sprint(this, strcat("^1You'll be dead in ", ftos(this.killindicator.cnt), " seconds\n"));
144
145                         IL_EACH(g_clones, it.enemy == this && !(it.effects & CSQCMODEL_EF_RESPAWNGHOST) && !it.killindicator,
146                         {
147                                 it.killindicator = new(killindicator);
148                                 it.killindicator.owner = it;
149                                 it.killindicator.scale = 0.5;
150                                 setattachment(it.killindicator, it, "");
151                                 setorigin(it.killindicator, '0 0 52');
152                                 setthink(it.killindicator, KillIndicator_Think);
153                                 it.killindicator.nextthink = starttime + (it.lip) * 0.05;
154                                 //clientkilltime = max(clientkilltime, it.killindicator.nextthink + 0.05);
155                                 it.killindicator.cnt = ceil(killtime);
156                         });
157                         this.lip = 0;
158                 }
159         }
160         if (this.killindicator)
161         {
162                 Notification notif;
163                 if (targetteam == 0) // just die
164                 {
165                         this.killindicator.colormod = '0 0 0';
166                         notif = CENTER_TEAMCHANGE_SUICIDE;
167                 }
168                 else if (targetteam == -1) // auto
169                 {
170                         this.killindicator.colormod = '0 1 0';
171                         notif = CENTER_TEAMCHANGE_AUTO;
172                 }
173                 else if (targetteam == -2) // spectate
174                 {
175                         this.killindicator.colormod = '0.5 0.5 0.5';
176                         notif = CENTER_TEAMCHANGE_SPECTATE;
177                 }
178                 else
179                 {
180                         this.killindicator.colormod = Team_ColorRGB(targetteam);
181                         notif = APP_TEAM_NUM(targetteam, CENTER_TEAMCHANGE);
182                 }
183                 if (IS_REAL_CLIENT(this) && this.killindicator.cnt > 0)
184                         Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, notif, this.killindicator.cnt);
185         }
186
187 }
188
189 void ClientKill_Silent(entity this, float _delay)
190 {
191         this.killindicator = new(killindicator);
192         this.killindicator.owner = this;
193         setthink(this.killindicator, KillIndicator_Think);
194         this.killindicator.nextthink = time + (this.lip) * 0.05;
195         this.killindicator.cnt = ceil(_delay);
196         this.killindicator.count = 1; // this is used to indicate that it should be silent
197         this.lip = 0;
198 }
199
200 // Called when a client types 'kill' in the console
201 void ClientKill(entity this)
202 {
203         if (game_stopped || this.player_blocked || STAT(FROZEN, this))
204                 return;
205
206         ClientKill_TeamChange(this, 0);
207 }