8 self.model = "models/nexball/ball.md3";
12 precache_model(self.model);
13 setmodel(self, self.model);
14 setsize(self, BALL_MINS, BALL_MAXS);
15 ball_scale = self.scale;
16 self.classname = "keepawayball";
17 self.damageforcescale = cvar("g_keepawayball_damageforcescale");
18 self.effects = self.effects | EF_FULLBRIGHT;
19 self.movetype = MOVETYPE_BOUNCE;
20 self.touch = ka_TouchEvent;
21 self.think = ka_SpawnBall;
22 self.nextthink = time;
24 self.reset = ka_Reset;
27 // todo: Waypoints and radar
28 //WaypointSprite_AttachCarrier();
33 if(MoveToRandomMapLocation(self, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
35 makevectors(self.angles);
36 self.movetype = MOVETYPE_BOUNCE;
37 self.velocity = '0 0 200';
38 self.angles = '0 0 0';
39 self.solid = SOLID_TRIGGER;
40 //self.touch = ka_TouchEvent;
41 self.think = ka_SpawnBall;
42 self.nextthink = time + cvar("g_keepawayball_respawntime");
46 // sorry, can't spawn, better luck next frame
47 self.think = ka_SpawnBall;
48 self.nextthink = time;
52 void ka_TouchEvent(entity plyr)
54 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
56 self.think = ka_SpawnBall;
57 self.nextthink = time;
64 if ((other.classname != "player" || other.health < 1) && (time > self.ctf_droptime + cvar("g_keepawayball_respawntime")))
70 other.ballcarried = self;
71 setattachment(self, other, "");
72 setorigin(self, BALL_ATTACHORG);
74 self.velocity = '0 0 0';
75 self.movetype = MOVETYPE_NONE;
76 self.touch = SUB_Null;
79 self.think = SUB_Null;
82 self.glow_color = cvar("g_keepawayball_trail_color");
83 self.glowtrail = TRUE;
87 bprint(other.netname, "^7 has picked up the ball!\n");
88 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
89 WriteString(MSG_BROADCAST, strcat("\n\n", other.netname, "^7 has picked up the ball!\n"));
90 sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NORM);
92 PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1);
94 // todo: Waypoints and radar
97 void ka_DropEvent(entity plyr, entity ball)
99 setattachment(ball, world, "");
100 ball.movetype = MOVETYPE_BOUNCE;
101 ball.solid = SOLID_TRIGGER;
102 ball.wait = time + 1;
103 ball.ctf_droptime = time;
104 ball.think = ka_SpawnBall;
105 ball.nextthink = time + cvar("g_keepawayball_respawntime");
106 ball.touch = ka_TouchEvent;
107 plyr.effects = EF_LOWPRECISION;
110 setorigin(ball, plyr.origin + '0 0 10');
111 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
113 bprint(plyr.netname, "^7 has dropped the ball!\n");
114 WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
115 WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n"));
116 sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NORM);
118 PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1);
121 //WaypointSprite_AttachCarrier("ka-ball", ball);
122 //WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier);
124 ball.owner.kaballcarried = world;
129 void ka_CheckWinner()
134 MUTATOR_HOOKFUNCTION(ka_PlayerDies)
139 float temp_tag_players_count;
140 temp_tag_players_count = tag_players_count;
142 if(frag_target.tagcolor == frag_target.tagcolor_original) // if this is the first time we die... (our tagcolor remained unchanged)
144 for(i = 0; i < temp_tag_players_count; ++i) // check other players...
147 if(e == world) // empty slot, skip to next
149 if(temp_tag_players_count < TAGCOLOR_MAX - 1) // just in case
150 ++temp_tag_players_count;
154 if(e.tagcolor == frag_target.tagcolor_original) // and see if they have our original tag color
156 tag_GetFragAttackers_ColorOwner();
157 centerprint(e, strcat("^1Your master ^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
158 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.
159 setcolor(e, 16 * e.tagcolor + e.tagcolor);
165 frag_target.tagcolor = frag_attacker.tagcolor;
166 setcolor(frag_target, 16 * frag_target.tagcolor + frag_target.tagcolor);
169 tag_GetFragAttackers_ColorOwner();
172 color_owner_green = "^2your own";
173 centerprint(frag_attacker, strcat("^2You tagged ^7", frag_target.netname, " ^2with ^7", color_owner_green, " ^2color.\n"));
176 color_owner_red = "^1their own";
177 centerprint(frag_target, strcat("^1You were tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n"));
178 bprint("^7", frag_target.netname, "^1 was tagged by ^7", frag_attacker.netname, " ^1with ^7", color_owner_red, " ^1color.\n");
180 frag_target.health = cvar("g_balance_health_start"); // "respawn" the player :P
187 MUTATOR_HOOKFUNCTION(tag_RemovePlayer)
189 if(self.tag_playernum == -1)
190 return 0; // nothing to remove
193 /*for (i = self.tag_playernum; i < tag_players_count; ++i)
195 tag_players[i] = tag_players[i+1];
196 tag_players[i].tag_playernum = tag_players[i].tag_playernum - 1;
200 tag_players[self.tag_playernum] = world;
201 tag_players_count = tag_players_count - 1;
203 // if other players have our color, randomize their color
204 entity e, random_player;
205 float temp_tag_players_count;
206 temp_tag_players_count = tag_players_count;
208 if(!next_round) // ... but ONLY if next_round isn't set. We don't care about the colors if the round has already ended
209 for(i = 0; i < temp_tag_players_count; ++i) // check other players...
212 if(e == world) // empty slot, skip to next
214 if(temp_tag_players_count < TAGCOLOR_MAX - 1) // just in case
215 ++temp_tag_players_count;
219 if(e.tagcolor == self.tagcolor_original) // and see if they have our original tag color
221 for(j = 0; j < 100; ++j) // try 100 times to find a color that isn't the same as our color. If this fails we are either damn unlucky, or there are really only players left of our color
223 random_player = tag_players[floor(random() * (TAGCOLOR_MAX - 1))];
225 if(random_player == world) // hit empty slot, try again
228 if(random_player.tagcolor != self.tagcolor_original) // break if we found another color
233 e.tagcolor = random_player.tagcolor;
234 setcolor(e, 16 * e.tagcolor + e.tagcolor);
238 self.tag_playernum = -1;
240 if(tag_players_count > 1 && time > warmup)
246 MUTATOR_HOOKFUNCTION(tag_GiveFragsForKill)
248 frag_score = 0; // no frags counted in Tag, maybe later (TODO)
252 MUTATOR_HOOKFUNCTION(tag_PlayerPreThink)
254 setcolor(self, 16 * self.tagcolor + self.tagcolor); // prevent cheating by changing player colors
260 MUTATOR_DEFINITION(gamemode_ka)
262 MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY);
263 MUTATOR_HOOK(ClientDisconnect, ka_RemovePlayer, CBC_ORDER_ANY);
264 MUTATOR_HOOK(PlayerDies, ka_PlayerDies, CBC_ORDER_ANY);
265 //MUTATOR_HOOK(PlayerSpawn, ka_PlayerSpawn, CBC_ORDER_ANY);
266 //MUTATOR_HOOK(GiveFragsForKill, ka_GiveFragsForKill, CBC_ORDER_FIRST);
267 //MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_FIRST);
271 if(time > 1) // game loads at time 1
272 error("This is a game type and it cannot be added at runtime.");
280 error("This is a game type and it cannot be removed at runtime.");