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