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