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;
26 self.model = "models/nexball/ball.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();
51 if(MoveToRandomMapLocation(self, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
53 makevectors(self.angles);
54 self.movetype = MOVETYPE_BOUNCE;
55 self.velocity = '0 0 200';
56 self.angles = '0 0 0';
57 self.solid = SOLID_TRIGGER;
58 //self.touch = ka_TouchEvent;
59 self.think = ka_RespawnBall;
60 self.nextthink = time + cvar("g_keepawayball_respawntime");
64 // sorry, can't spawn, better luck next frame
65 self.think = ka_RespawnBall;
66 self.nextthink = time;
70 void ka_TouchEvent(entity plyr)
72 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
74 self.think = ka_SpawnBall;
75 self.nextthink = time;
82 if ((other.classname != "player" || other.health < 1) && (time > self.ctf_droptime + cvar("g_keepawayball_respawntime")))
88 other.ballcarried = self;
89 setattachment(self, other, "");
90 setorigin(self, BALL_ATTACHORG);
92 self.velocity = '0 0 0';
93 self.movetype = MOVETYPE_NONE;
94 self.touch = SUB_Null;
97 self.think = SUB_Null;
100 self.glow_color = cvar("g_keepawayball_trail_color");
101 self.glow_trail = TRUE;
105 bprint(other.netname, "^7 has picked up the ball!\n");
106 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
107 WriteString(MSG_BROADCAST, strcat("\n\n", other.netname, "^7 has picked up the ball!\n"));
108 sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NORM);
110 PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
112 // todo: Waypoints and radar
115 MUTATOR_HOOKFUNCTION(ka_RemovePlayer)
118 ball = self.ballcarried;
120 setattachment(ball, world, "");
121 ball.movetype = MOVETYPE_BOUNCE;
122 ball.solid = SOLID_TRIGGER;
123 ball.wait = time + 1;
124 ball.ctf_droptime = time;
125 ball.think = ka_SpawnBall;
126 ball.nextthink = time + cvar("g_keepawayball_respawntime");
127 ball.touch = ka_TouchEvent;
128 self.effects = EF_LOWPRECISION;
131 setorigin(ball, self.origin + '0 0 10');
132 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
134 bprint(self.netname, "^7 has dropped the ball!\n");
135 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
136 WriteString(MSG_BROADCAST, strcat("\n\n", self.netname, "^7 has dropped the ball!\n"));
137 sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NORM);
139 PlayerScore_Add(self, SP_KEEPAWAY_DROPS, 1);
142 //WaypointSprite_AttachCarrier("ka-ball", ball);
143 //WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
145 ball.owner.ballcarried = world;
152 void ka_DropEvent(entity plyr, entity ball)
154 setattachment(ball, world, "");
155 ball.movetype = MOVETYPE_BOUNCE;
156 ball.solid = SOLID_TRIGGER;
157 ball.wait = time + 1;
158 ball.ctf_droptime = time;
159 ball.think = ka_SpawnBall;
160 ball.nextthink = time + cvar("g_keepawayball_respawntime");
161 ball.touch = ka_TouchEvent;
162 plyr.effects = EF_LOWPRECISION;
165 setorigin(ball, plyr.origin + '0 0 10');
166 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
168 bprint(plyr.netname, "^7 has dropped the ball!\n");
169 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
170 WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n"));
171 sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NORM);
173 PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1);
176 //WaypointSprite_AttachCarrier("ka-ball", ball);
177 //WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
179 ball.owner.kaballcarried = world;
184 void ka_CheckWinner()
189 MUTATOR_HOOKFUNCTION(ka_PlayerDies)
194 float temp_tag_players_count;
195 temp_tag_players_count = tag_players_count;
197 if(frag_target.tagcolor == frag_target.tagcolor_original) // if this is the first time we die... (our tagcolor remained unchanged)
199 for(i = 0; i < temp_tag_players_count; ++i) // check other players...
202 if(e == world) // empty slot, skip to next
204 if(temp_tag_players_count < TAGCOLOR_MAX - 1) // just in case
205 ++temp_tag_players_count;
209 if(e.tagcolor == frag_target.tagcolor_original) // and see if they have our original tag color
211 tag_GetFragAttackers_ColorOwner();
212 centerprint(e, strcat("^1Your master ^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
213 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.
214 setcolor(e, 16 * e.tagcolor + e.tagcolor);
220 frag_target.tagcolor = frag_attacker.tagcolor;
221 setcolor(frag_target, 16 * frag_target.tagcolor + frag_target.tagcolor);
224 tag_GetFragAttackers_ColorOwner();
227 color_owner_green = "^2your own";
228 centerprint(frag_attacker, strcat("^2You tagged ^7", frag_target.netname, " ^2with ^7", color_owner_green, " ^2color.\n"));
231 color_owner_red = "^1their own";
232 centerprint(frag_target, strcat("^1You were tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
233 bprint("^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n");
235 frag_target.health = cvar("g_balance_health_start"); // "respawn" the player :P
242 MUTATOR_HOOKFUNCTION(tag_RemovePlayer)
248 MUTATOR_HOOKFUNCTION(tag_GiveFragsForKill)
250 frag_score = 0; // no frags counted in Tag, maybe later (TODO)
254 MUTATOR_HOOKFUNCTION(tag_PlayerPreThink)
256 setcolor(self, 16 * self.tagcolor + self.tagcolor); // prevent cheating by changing player colors
262 MUTATOR_DEFINITION(gamemode_keepaway)
264 MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY);
265 MUTATOR_HOOK(ClientDisconnect, ka_RemovePlayer, CBC_ORDER_ANY);
266 //MUTATOR_HOOK(PlayerDies, ka_PlayerDies, CBC_ORDER_ANY);
267 //MUTATOR_HOOK(PlayerSpawn, ka_PlayerSpawn, CBC_ORDER_ANY);
268 //MUTATOR_HOOK(GiveFragsForKill, ka_GiveFragsForKill, CBC_ORDER_FIRST);
269 //MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_FIRST);
273 if(time > 1) // game loads at time 1
274 error("This is a game type and it cannot be added at runtime.");
282 error("This is a game type and it cannot be removed at runtime.");