1 void ka_SpawnBall(void);
2 void ka_TouchEvent(entity);
3 void ka_RespawnBall(void);
10 precache_sound("keepaway/pickedup.wav");
11 precache_sound("keepaway/dropped.wav");
15 e.think = ka_SpawnBall;
19 void ka_SpawnBall() // self = the ball
26 self.model = "models/orbs/orbblue.md3";
30 precache_model(self.model);
31 setmodel(self, self.model);
32 setsize(self, BALL_MINS, BALL_MAXS);
33 ball_scale = self.scale;
34 self.classname = "keepawayball";
35 self.damageforcescale = cvar("g_keepawayball_damageforcescale");
36 self.effects = self.effects | EF_FULLBRIGHT;
37 self.movetype = MOVETYPE_BOUNCE;
38 self.touch = ka_TouchEvent;
39 self.think = ka_RespawnBall;
40 self.nextthink = time;
42 //self.reset = ka_Reset;
45 // todo: Waypoints and radar
46 WaypointSprite_AttachCarrier("nb-ball", self);
47 //bprint("^4ka_SpawnBall was just called!\n");
52 if(MoveToRandomMapLocation(self, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
54 makevectors(self.angles);
55 self.movetype = MOVETYPE_BOUNCE;
56 self.velocity = '0 0 200';
57 self.angles = '0 0 0';
58 self.solid = SOLID_TRIGGER;
59 //self.touch = ka_TouchEvent;
60 self.think = ka_RespawnBall;
61 self.nextthink = time + cvar("g_keepawayball_respawntime");
65 // sorry, can't spawn, better luck next frame
66 self.think = ka_RespawnBall;
67 self.nextthink = time;
69 //bprint("^4ka_RespawnBall was just called!\n");
72 void ka_TouchEvent(entity plyr)
74 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
76 self.think = ka_SpawnBall;
77 self.nextthink = time;
84 if(other.classname != "player" || other.health < 1)
88 //if(time > self.ctf_droptime + cvar("g_keepawayball_respawntime"))
92 other.kaballcarried = self;
93 setattachment(self, other, "");
94 setorigin(self, BALL_ATTACHORG);
96 self.velocity = '0 0 0';
97 self.movetype = MOVETYPE_NONE;
98 self.touch = SUB_Null;
101 self.think = SUB_Null;
104 self.glow_color = cvar("g_keepawayball_trail_color");
105 self.glow_trail = TRUE;
109 bprint(other.netname, "^7 has picked up the ball!\n");
110 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
111 WriteString(MSG_BROADCAST, strcat("\n\n", other.netname, "^7 has picked up the ball!\n"));
112 sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NORM);
114 PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
116 // todo: Waypoints and radar
119 MUTATOR_HOOKFUNCTION(ka_RemovePlayer)
121 if(self.kaballcarried) {
123 ball = self.kaballcarried;
125 setattachment(ball, world, "");
126 ball.movetype = MOVETYPE_BOUNCE;
127 ball.solid = SOLID_TRIGGER;
128 ball.wait = time + 1;
129 ball.ctf_droptime = time;
130 ball.think = ka_SpawnBall;
131 ball.nextthink = time + cvar("g_keepawayball_respawntime");
132 ball.touch = ka_TouchEvent;
133 self.effects = EF_LOWPRECISION;
136 setorigin(ball, self.origin + '0 0 10'); // FIX ME: If a player becomes spectator, the hook function is given AFTER this happens, which means the origin given is after they already moved to another position, not where they died!
137 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
139 bprint(self.netname, "^7 has dropped the ball!\n");
140 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
141 WriteString(MSG_BROADCAST, strcat("\n\n", self.netname, "^7 has dropped the ball!\n"));
142 sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NORM);
144 PlayerScore_Add(self, SP_KEEPAWAY_DROPS, 1);
147 WaypointSprite_AttachCarrier("nb-ball", ball);
148 WaypointSprite_Kill(self.waypointsprite_attachedforcarrier);
150 ball.owner.kaballcarried = world;
157 void ka_DropEvent(entity plyr, entity ball)
159 setattachment(ball, world, "");
160 ball.movetype = MOVETYPE_BOUNCE;
161 ball.solid = SOLID_TRIGGER;
162 ball.wait = time + 1;
163 ball.ctf_droptime = time;
164 ball.think = ka_SpawnBall;
165 ball.nextthink = time + cvar("g_keepawayball_respawntime");
166 ball.touch = ka_TouchEvent;
167 plyr.effects = EF_LOWPRECISION;
170 setorigin(ball, plyr.origin + '0 0 10');
171 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
173 bprint(plyr.netname, "^7 has dropped the ball!\n");
174 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
175 WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n"));
176 sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NORM);
178 PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1);
181 //WaypointSprite_AttachCarrier("ka-ball", ball);
182 //WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
184 ball.owner.kaballcarried = world;
189 void ka_CheckWinner()
194 MUTATOR_HOOKFUNCTION(ka_PlayerDies)
199 float temp_tag_players_count;
200 temp_tag_players_count = tag_players_count;
202 if(frag_target.tagcolor == frag_target.tagcolor_original) // if this is the first time we die... (our tagcolor remained unchanged)
204 for(i = 0; i < temp_tag_players_count; ++i) // check other players...
207 if(e == world) // empty slot, skip to next
209 if(temp_tag_players_count < TAGCOLOR_MAX - 1) // just in case
210 ++temp_tag_players_count;
214 if(e.tagcolor == frag_target.tagcolor_original) // and see if they have our original tag color
216 tag_GetFragAttackers_ColorOwner();
217 centerprint(e, strcat("^1Your master ^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
218 e.tagcolor = frag_attacker.tagcolor; // if so, remove it, our tag color has now "died out" from this round and we can not win anymore. The attacker will "summon" all of our previously fragged targets, and also us.
219 setcolor(e, 16 * e.tagcolor + e.tagcolor);
225 frag_target.tagcolor = frag_attacker.tagcolor;
226 setcolor(frag_target, 16 * frag_target.tagcolor + frag_target.tagcolor);
229 tag_GetFragAttackers_ColorOwner();
232 color_owner_green = "^2your own";
233 centerprint(frag_attacker, strcat("^2You tagged ^7", frag_target.netname, " ^2with ^7", color_owner_green, " ^2color.\n"));
236 color_owner_red = "^1their own";
237 centerprint(frag_target, strcat("^1You were tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
238 bprint("^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n");
240 frag_target.health = cvar("g_balance_health_start"); // "respawn" the player :P
247 MUTATOR_HOOKFUNCTION(tag_RemovePlayer)
253 MUTATOR_HOOKFUNCTION(tag_GiveFragsForKill)
255 frag_score = 0; // no frags counted in Tag, maybe later (TODO)
259 MUTATOR_HOOKFUNCTION(tag_PlayerPreThink)
261 setcolor(self, 16 * self.tagcolor + self.tagcolor); // prevent cheating by changing player colors
267 MUTATOR_DEFINITION(gamemode_keepaway)
269 MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY);
270 MUTATOR_HOOK(ClientDisconnect, ka_RemovePlayer, CBC_ORDER_ANY);
271 MUTATOR_HOOK(PlayerDies, ka_RemovePlayer, CBC_ORDER_ANY);
272 //MUTATOR_HOOK(PlayerSpawn, ka_PlayerSpawn, CBC_ORDER_ANY);
273 //MUTATOR_HOOK(GiveFragsForKill, ka_GiveFragsForKill, CBC_ORDER_FIRST);
274 //MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_FIRST);
278 if(time > 1) // game loads at time 1
279 error("This is a game type and it cannot be added at runtime.");
287 error("This is a game type and it cannot be removed at runtime.");