X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fmutators%2Fgamemode_nexball.qc;h=4c081ab445f0c3abab6bc944c12c3a73edafc54e;hb=a97b89297fa91ae42b9d56c262662eb34ede3e45;hp=85377836d5f432887b77737c25a8036978cc96b1;hpb=57e8b59f96ec28979c3dc01811412c9c26e60fdc;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/mutators/gamemode_nexball.qc b/qcsrc/server/mutators/gamemode_nexball.qc index 85377836d..f65e05843 100644 --- a/qcsrc/server/mutators/gamemode_nexball.qc +++ b/qcsrc/server/mutators/gamemode_nexball.qc @@ -1,3 +1,23 @@ +#include "gamemode_nexball.qh" +#include "../_all.qh" + +#include "gamemode.qh" + +float autocvar_g_nexball_basketball_bouncefactor; +float autocvar_g_nexball_basketball_bouncestop; +float autocvar_g_nexball_basketball_carrier_highspeed; +bool autocvar_g_nexball_basketball_meter; +float autocvar_g_nexball_basketball_meter_maxpower; +float autocvar_g_nexball_basketball_meter_minpower; +float autocvar_g_nexball_delay_collect; +float autocvar_g_nexball_delay_goal; +float autocvar_g_nexball_delay_start; +float autocvar_g_nexball_football_bouncefactor; +float autocvar_g_nexball_football_bouncestop; +bool autocvar_g_nexball_radar_showallplayers; +bool autocvar_g_nexball_sound_bounce; +int autocvar_g_nexball_trail_color; + float autocvar_g_nexball_safepass_turnrate; float autocvar_g_nexball_safepass_maxdist; float autocvar_g_nexball_safepass_holdtime; @@ -8,9 +28,9 @@ vector autocvar_g_nexball_viewmodel_offset; void basketball_touch(); void football_touch(); void ResetBall(); -#define NBM_NONE 0 -#define NBM_FOOTBALL 2 -#define NBM_BASKETBALL 4 +const float NBM_NONE = 0; +const float NBM_FOOTBALL = 2; +const float NBM_BASKETBALL = 4; float nexball_mode; float OtherTeam(float t) //works only if there are two teams on the map! @@ -22,6 +42,17 @@ float OtherTeam(float t) //works only if there are two teams on the map! return e.team; } +const float ST_NEXBALL_GOALS = 1; +const float SP_NEXBALL_GOALS = 4; +const float SP_NEXBALL_FAULTS = 5; +void nb_ScoreRules(float teams) +{ + ScoreRules_basics(teams, 0, 0, true); + ScoreInfo_SetLabel_TeamScore( ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY); + ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY); + ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER); + ScoreRules_basics_end(); +} void LogNB(string mode, entity actor) { @@ -35,26 +66,24 @@ void LogNB(string mode, entity actor) } void ball_restart(void) -{ +{SELFPARAM(); if(self.owner) DropBall(self, self.owner.origin, '0 0 0'); ResetBall(); } void nexball_setstatus(void) -{ - entity oldself; +{SELFPARAM(); self.items &= ~IT_KEY1; if(self.ballcarried) { if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time)) { bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n"); - oldself = self; - self = self.ballcarried; + setself(self.ballcarried); DropBall(self, self.owner.origin, '0 0 0'); ResetBall(); - self = oldself; + setself(this); } else self.items |= IT_KEY1; @@ -62,34 +91,34 @@ void nexball_setstatus(void) } void relocate_nexball(void) -{ - tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, TRUE, self); +{SELFPARAM(); + tracebox(self.origin, BALL_MINS, BALL_MAXS, self.origin, true, self); if(trace_startsolid) { vector o; o = self.origin; if(!move_out_of_solid(self)) objerror("could not get out of solid at all!"); - print("^1NOTE: this map needs FIXING. ", self.classname, " at ", vtos(o - '0 0 1')); - print(" needs to be moved out of solid, e.g. by '", ftos(self.origin_x - o_x)); - print(" ", ftos(self.origin_y - o_y)); - print(" ", ftos(self.origin_z - o_z), "'\n"); + LOG_INFO("^1NOTE: this map needs FIXING. ", self.classname, " at ", vtos(o - '0 0 1')); + LOG_INFO(" needs to be moved out of solid, e.g. by '", ftos(self.origin.x - o.x)); + LOG_INFO(" ", ftos(self.origin.y - o.y)); + LOG_INFO(" ", ftos(self.origin.z - o.z), "'\n"); self.origin = o; } } void DropOwner(void) -{ +{SELFPARAM(); entity ownr; ownr = self.owner; DropBall(self, ownr.origin, ownr.velocity); - makevectors(ownr.v_angle_y * '0 1 0'); + makevectors(ownr.v_angle.y * '0 1 0'); ownr.velocity += ('0 0 0.75' - v_forward) * 1000; ownr.flags &= ~FL_ONGROUND; } void GiveBall(entity plyr, entity ball) -{ +{SELFPARAM(); entity ownr; if((ownr = ball.owner)) @@ -128,7 +157,7 @@ void GiveBall(entity plyr, entity ball) ball.effects |= EF_NOSHADOW; ball.scale = 1; // scale down. - WaypointSprite_AttachCarrier("nb-ball", plyr, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); + WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER); WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); if(autocvar_g_nexball_basketball_delay_hold) @@ -137,15 +166,15 @@ void GiveBall(entity plyr, entity ball) ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold; } - ownr = self; - self = plyr; - self.weaponentity.weapons = self.weapons; - self.weaponentity.switchweapon = self.weapon; - self.weapons = WEPSET_PORTO; - WEP_ACTION(WEP_PORTO, WR_RESETPLAYER); - self.switchweapon = WEP_PORTO; - W_SwitchWeapon(WEP_PORTO); - self = ownr; + plyr.weaponentity.weapons = plyr.weapons; + plyr.weaponentity.switchweapon = plyr.weapon; + plyr.weapons = WEPSET(NEXBALL); + setself(plyr); + Weapon w = WEP_NEXBALL; + w.wr_resetplayer(w); + plyr.switchweapon = WEP_NEXBALL.m_id; + W_SwitchWeapon(WEP_NEXBALL.m_id); + setself(this); } void DropBall(entity ball, vector org, vector vel) @@ -172,7 +201,7 @@ void DropBall(entity ball, vector org, vector vel) } WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier); - WaypointSprite_Spawn("nb-ball", 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // no health bar please + WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', world, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); ball.owner.ballcarried = world; @@ -180,7 +209,7 @@ void DropBall(entity ball, vector org, vector vel) } void InitBall(void) -{ +{SELFPARAM(); if(gameover) return; self.flags &= ~FL_ONGROUND; self.movetype = MOVETYPE_BOUNCE; @@ -193,14 +222,14 @@ void InitBall(void) self.nextthink = time + autocvar_g_nexball_delay_idle + 3; self.teamtime = 0; self.pusher = world; - self.team = FALSE; - sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM); + self.team = false; + _sound(self, CH_TRIGGER, self.noise1, VOL_BASE, ATTEN_NORM); WaypointSprite_Ping(self.waypointsprite_attachedforcarrier); LogNB("init", world); } void ResetBall(void) -{ +{SELFPARAM(); if(self.cnt < 2) // step 1 { if(time == self.teamtime) @@ -225,7 +254,7 @@ void ResetBall(void) { // dprint("Step 4: time: ", ftos(time), "\n"); if(vlen(self.origin - self.spawnorigin) > 10) // should not happen anymore - dprint("The ball moved too far away from its spawn origin.\nOffset: ", + LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ", vtos(self.origin - self.spawnorigin), " Velocity: ", vtos(self.velocity), "\n"); self.velocity = '0 0 0'; setorigin(self, self.spawnorigin); // make sure it's positioned correctly anyway @@ -236,12 +265,12 @@ void ResetBall(void) } void football_touch(void) -{ +{SELFPARAM(); if(other.solid == SOLID_BSP) { if(time > self.lastground + 0.1) { - sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); + _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); self.lastground = time; } if(vlen(self.velocity) && !self.cnt) @@ -270,7 +299,7 @@ void football_touch(void) } else if(autocvar_g_nexball_football_physics == 2) // 2nd mod try: totally independant. Really playable! { - makevectors(other.v_angle_y * '0 1 0'); + makevectors(other.v_angle.y * '0 1 0'); self.velocity = other.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up; } else // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant) @@ -282,13 +311,13 @@ void football_touch(void) } void basketball_touch(void) -{ +{SELFPARAM(); if(other.ballcarried) { football_touch(); return; } - if(!self.cnt && IS_PLAYER(other) && !other.frozen && (other != self.nb_dropper || time > self.nb_droptime + autocvar_g_nexball_delay_collect)) + if(!self.cnt && IS_PLAYER(other) && !other.frozen && !other.deadflag && (other != self.nb_dropper || time > self.nb_droptime + autocvar_g_nexball_delay_collect)) { if(other.health <= 0) return; @@ -297,14 +326,14 @@ void basketball_touch(void) } else if(other.solid == SOLID_BSP) { - sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); + _sound(self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); if(vlen(self.velocity) && !self.cnt) self.nextthink = min(time + autocvar_g_nexball_delay_idle, self.teamtime); } } void GoalTouch(void) -{ +{SELFPARAM(); entity ball; float isclient, pscore, otherteam; string pname; @@ -363,7 +392,7 @@ void GoalTouch(void) pscore = 1; } - sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE); + _sound(ball, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NONE); if(ball.team && pscore) { @@ -395,7 +424,7 @@ void GoalTouch(void) //=======================// // team ents // //=======================// -void spawnfunc_nexball_team(void) +spawnfunc(nexball_team) { if(!g_nexball) { @@ -407,7 +436,7 @@ void spawnfunc_nexball_team(void) void nb_spawnteam(string teamname, float teamcolor) { - dprint("^2spawned team ", teamname, "\n"); + LOG_TRACE("^2spawned team ", teamname, "\n"); entity e; e = spawn(); e.classname = "nexball_team"; @@ -419,54 +448,44 @@ void nb_spawnteam(string teamname, float teamcolor) void nb_spawnteams(void) { - float t_r = 0, t_b = 0, t_y = 0, t_p = 0; + bool t_red = false, t_blue = false, t_yellow = false, t_pink = false; entity e; for(e = world; (e = find(e, classname, "nexball_goal"));) { switch(e.team) { case NUM_TEAM_1: - if(!t_r) + if(!t_red) { nb_spawnteam("Red", e.team-1) ; - t_r = 1; + t_red = true; } break; case NUM_TEAM_2: - if(!t_b) + if(!t_blue) { nb_spawnteam("Blue", e.team-1) ; - t_b = 1; + t_blue = true; } break; case NUM_TEAM_3: - if(!t_y) + if(!t_yellow) { nb_spawnteam("Yellow", e.team-1); - t_y = 1; + t_yellow = true; } break; case NUM_TEAM_4: - if(!t_p) + if(!t_pink) { nb_spawnteam("Pink", e.team-1) ; - t_p = 1; + t_pink = true; } break; } } } -// scoreboard setup -void nb_ScoreRules(float teams) -{ - ScoreRules_basics(teams, 0, 0, TRUE); - ScoreInfo_SetLabel_TeamScore( ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore( SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY); - ScoreInfo_SetLabel_PlayerScore(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER); - ScoreRules_basics_end(); -} - void nb_delayedinit(void) { if(find(world, classname, "nexball_team") == world) @@ -480,7 +499,7 @@ void nb_delayedinit(void) //=======================// void SpawnBall(void) -{ +{SELFPARAM(); if(!g_nexball) { remove(self); return; } // balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine @@ -492,7 +511,7 @@ void SpawnBall(void) } precache_model(self.model); - setmodel(self, self.model); + _setmodel(self, self.model); setsize(self, BALL_MINS, BALL_MAXS); ball_scale = self.scale; @@ -504,7 +523,7 @@ void SpawnBall(void) if(cvar(strcat("g_", self.classname, "_trail"))) //nexball_basketball :p { self.glow_color = autocvar_g_nexball_trail_color; - self.glow_trail = TRUE; + self.glow_trail = true; } self.movetype = MOVETYPE_FLY; @@ -512,26 +531,26 @@ void SpawnBall(void) if(!autocvar_g_nexball_sound_bounce) self.noise = ""; else if(self.noise == "") - self.noise = "sound/nexball/bounce.wav"; + self.noise = SND(NB_BOUNCE); //bounce sound placeholder (FIXME) if(self.noise1 == "") - self.noise1 = "sound/nexball/drop.wav"; + self.noise1 = SND(NB_DROP); //ball drop sound placeholder (FIXME) if(self.noise2 == "") - self.noise2 = "sound/nexball/steal.wav"; + self.noise2 = SND(NB_STEAL); //stealing sound placeholder (FIXME) if(self.noise) precache_sound(self.noise); precache_sound(self.noise1); precache_sound(self.noise2); - WaypointSprite_AttachCarrier("nb-ball", self, RADARICON_FLAGCARRIER, BALL_SPRITECOLOR); // the ball's team is not set yet, no rule update needed + WaypointSprite_AttachCarrier(WP_NbBall, self, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed self.reset = ball_restart; self.think = InitBall; self.nextthink = game_starttime + autocvar_g_nexball_delay_start; } -void spawnfunc_nexball_basketball(void) +spawnfunc(nexball_basketball) { nexball_mode |= NBM_BASKETBALL; self.classname = "nexball_basketball"; @@ -554,7 +573,7 @@ void spawnfunc_nexball_basketball(void) SpawnBall(); } -void spawnfunc_nexball_football(void) +spawnfunc(nexball_football) { nexball_mode |= NBM_FOOTBALL; self.classname = "nexball_football"; @@ -566,24 +585,25 @@ void spawnfunc_nexball_football(void) } float nb_Goal_Customize() -{ +{SELFPARAM(); entity e, wp_owner; e = WaypointSprite_getviewentity(other); wp_owner = self.owner; - if(SAME_TEAM(e, wp_owner)) { return FALSE; } + if(SAME_TEAM(e, wp_owner)) { return false; } - return TRUE; + return true; } void SpawnGoal(void) -{ +{SELFPARAM(); if(!g_nexball) { remove(self); return; } EXACTTRIGGER_INIT; if(self.team != GOAL_OUT && Team_TeamToNumber(self.team) != -1) { - WaypointSprite_SpawnFixed("goal", (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE, ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0')); + entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (self.absmin + self.absmax) * 0.5, self, sprite, RADARICON_NONE); + wp.colormod = ((self.team) ? Team_ColorRGB(self.team) : '1 0.5 0'); self.sprite.customizeentityforclient = nb_Goal_Customize; } @@ -594,40 +614,40 @@ void SpawnGoal(void) self.touch = GoalTouch; } -void spawnfunc_nexball_redgoal(void) +spawnfunc(nexball_redgoal) { self.team = NUM_TEAM_1; SpawnGoal(); } -void spawnfunc_nexball_bluegoal(void) +spawnfunc(nexball_bluegoal) { self.team = NUM_TEAM_2; SpawnGoal(); } -void spawnfunc_nexball_yellowgoal(void) +spawnfunc(nexball_yellowgoal) { self.team = NUM_TEAM_3; SpawnGoal(); } -void spawnfunc_nexball_pinkgoal(void) +spawnfunc(nexball_pinkgoal) { self.team = NUM_TEAM_4; SpawnGoal(); } -void spawnfunc_nexball_fault(void) +spawnfunc(nexball_fault) { self.team = GOAL_FAULT; if(self.noise == "") - self.noise = "misc/typehit.wav"; + self.noise = SND(TYPEHIT); SpawnGoal(); } -void spawnfunc_nexball_out(void) +spawnfunc(nexball_out) { self.team = GOAL_OUT; if(self.noise == "") - self.noise = "misc/typehit.wav"; + self.noise = SND(TYPEHIT); SpawnGoal(); } @@ -635,34 +655,34 @@ void spawnfunc_nexball_out(void) //Spawnfuncs preserved for compatibility // -void spawnfunc_ball(void) +spawnfunc(ball) { - spawnfunc_nexball_football(); + spawnfunc_nexball_football(this); } -void spawnfunc_ball_football(void) +spawnfunc(ball_football) { - spawnfunc_nexball_football(); + spawnfunc_nexball_football(this); } -void spawnfunc_ball_basketball(void) +spawnfunc(ball_basketball) { - spawnfunc_nexball_basketball(); + spawnfunc_nexball_basketball(this); } // The "red goal" is defended by blue team. A ball in there counts as a point for red. -void spawnfunc_ball_redgoal(void) +spawnfunc(ball_redgoal) { - spawnfunc_nexball_bluegoal(); // I blame Revenant + spawnfunc_nexball_bluegoal(this); // I blame Revenant } -void spawnfunc_ball_bluegoal(void) +spawnfunc(ball_bluegoal) { - spawnfunc_nexball_redgoal(); // but he didn't mean to cause trouble :p + spawnfunc_nexball_redgoal(this); // but he didn't mean to cause trouble :p } -void spawnfunc_ball_fault(void) +spawnfunc(ball_fault) { - spawnfunc_nexball_fault(); + spawnfunc_nexball_fault(this); } -void spawnfunc_ball_bound(void) +spawnfunc(ball_bound) { - spawnfunc_nexball_out(); + spawnfunc_nexball_out(this); } //=======================// @@ -671,7 +691,7 @@ void spawnfunc_ball_bound(void) void W_Nexball_Think() -{ +{SELFPARAM(); //dprint("W_Nexball_Think\n"); //vector new_dir = steerlib_arrive(self.enemy.origin, 2500); vector new_dir = normalize(self.enemy.origin + '0 0 50' - self.origin); @@ -686,7 +706,7 @@ void W_Nexball_Think() } void W_Nexball_Touch(void) -{ +{SELFPARAM(); entity ball, attacker; attacker = self.owner; //self.think = func_null; @@ -694,14 +714,14 @@ void W_Nexball_Touch(void) PROJECTILE_TOUCH; if(attacker.team != other.team || autocvar_g_nexball_basketball_teamsteal) - if((ball = other.ballcarried) && !other.deadflag && (IS_PLAYER(attacker))) + if((ball = other.ballcarried) && !other.frozen && !other.deadflag && (IS_PLAYER(attacker))) { other.velocity = other.velocity + normalize(self.velocity) * other.damageforcescale * autocvar_g_balance_nexball_secondary_force; other.flags &= ~FL_ONGROUND; if(!attacker.ballcarried) { LogNB("stole", attacker); - sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM); + _sound(other, CH_TRIGGER, ball.noise2, VOL_BASE, ATTEN_NORM); if(SAME_TEAM(attacker, other) && time > attacker.teamkill_complain) { @@ -717,13 +737,13 @@ void W_Nexball_Touch(void) } void W_Nexball_Attack(float t) -{ +{SELFPARAM(); entity ball; float mul, mi, ma; if(!(ball = self.ballcarried)) return; - W_SetupShot(self, FALSE, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0); + W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0); tracebox(w_shotorg, BALL_MINS, BALL_MAXS, w_shotorg, MOVE_WORLDONLY, world); if(trace_startsolid) { @@ -740,24 +760,24 @@ void W_Nexball_Attack(float t) mi = autocvar_g_nexball_basketball_meter_minpower; ma = max(mi, autocvar_g_nexball_basketball_meter_maxpower); // avoid confusion //One triangle wave period with 1 as max - mul = 2 * mod(t, g_nexball_meter_period) / g_nexball_meter_period; + mul = 2 * (t % g_nexball_meter_period) / g_nexball_meter_period; if(mul > 1) mul = 2 - mul; mul = mi + (ma - mi) * mul; // range from the minimal power to the maximal power } - DropBall(ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * autocvar_g_balance_nexball_primary_speed * mul, FALSE)); + DropBall(ball, w_shotorg, W_CalculateProjectileVelocity(self.velocity, w_shotdir * autocvar_g_balance_nexball_primary_speed * mul, false)); //TODO: use the speed_up cvar too ?? } void W_Nexball_Attack2(void) -{ +{SELFPARAM(); if(self.ballcarried.enemy) { entity _ball = self.ballcarried; - W_SetupShot(self, FALSE, 4, "nexball/shoot1.wav", CH_WEAPON_A, 0); + W_SetupShot(self, false, 4, SND(NB_SHOOT1), CH_WEAPON_A, 0); DropBall(_ball, w_shotorg, trigger_push_calculatevelocity(_ball.origin, _ball.enemy, 32)); _ball.think = W_Nexball_Think; _ball.nextthink = time; @@ -767,12 +787,8 @@ void W_Nexball_Attack2(void) if(!autocvar_g_nexball_tackling) return; - entity missile; - if(!(balls & BALL_BASKET)) - return; - W_SetupShot(self, FALSE, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0); -// pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - missile = spawn(); + W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0); + entity missile = spawn(); missile.owner = self; missile.classname = "ballstealer"; @@ -793,17 +809,17 @@ void W_Nexball_Attack2(void) missile.effects = EF_BRIGHTFIELD | EF_LOWPRECISION; missile.flags = FL_PROJECTILE; - CSQCProjectile(missile, TRUE, PROJECTILE_ELECTRO, TRUE); + CSQCProjectile(missile, true, PROJECTILE_ELECTRO, true); } float ball_customize() -{ +{SELFPARAM(); if(!self.owner) { self.effects &= ~EF_FLAME; self.scale = 1; self.customizeentityforclient = func_null; - return TRUE; + return true; } if(other == self.owner) @@ -820,61 +836,54 @@ float ball_customize() self.scale = 1; } - return TRUE; + return true; } -float w_nexball_weapon(float req) -{ - if(req == WR_THINK) + METHOD(BallStealer, wr_think, void(BallStealer thiswep, entity actor, bool fire1, bool fire2)) { - if(self.BUTTON_ATCK) - if(weapon_prepareattack(0, autocvar_g_balance_nexball_primary_refire)) + if(fire1) + if(weapon_prepareattack(thiswep, actor, false, autocvar_g_balance_nexball_primary_refire)) if(autocvar_g_nexball_basketball_meter) { if(self.ballcarried && !self.metertime) self.metertime = time; else - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); + weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); } else { W_Nexball_Attack(-1); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); + weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); } - if(self.BUTTON_ATCK2) - if(weapon_prepareattack(1, autocvar_g_balance_nexball_secondary_refire)) + if(fire2) + if(weapon_prepareattack(thiswep, actor, true, autocvar_g_balance_nexball_secondary_refire)) { W_Nexball_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready); + weapon_thinkf(actor, WFRAME_FIRE2, autocvar_g_balance_nexball_secondary_animtime, w_ready); } - if(!self.BUTTON_ATCK && self.metertime && self.ballcarried) + if(!fire1 && self.metertime && self.ballcarried) { W_Nexball_Attack(time - self.metertime); // DropBall or stealing will set metertime back to 0 - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); + weapon_thinkf(actor, WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); } } - else if(req == WR_INIT) + METHOD(BallStealer, wr_setup, void(BallStealer thiswep)) { - precache_model("models/weapons/g_porto.md3"); - precache_model("models/weapons/v_porto.md3"); - precache_model("models/weapons/h_porto.iqm"); - precache_model("models/elaser.mdl"); - precache_sound("nexball/shoot1.wav"); - precache_sound("nexball/shoot2.wav"); - precache_sound("misc/typehit.wav"); + //weapon_setup(WEP_PORTO.m_id); } - else if(req == WR_SETUP) + METHOD(BallStealer, wr_checkammo1, bool(BallStealer thiswep)) { - //weapon_setup(WEP_PORTO); + return true; + } + METHOD(BallStealer, wr_checkammo2, bool(BallStealer thiswep)) + { + return true; } - // No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE - return TRUE; -} MUTATOR_HOOKFUNCTION(nexball_BallDrop) -{ +{SELFPARAM(); if(self.ballcarried && g_nexball) DropBall(self.ballcarried, self.origin, self.velocity); @@ -882,7 +891,7 @@ MUTATOR_HOOKFUNCTION(nexball_BallDrop) } MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink) -{ +{SELFPARAM(); makevectors(self.v_angle); if(nexball_mode & NBM_BASKETBALL) { @@ -893,9 +902,9 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink) self.ballcarried.customizeentityforclient = ball_customize; setorigin(self.ballcarried, self.origin + self.view_ofs + - v_forward * autocvar_g_nexball_viewmodel_offset_x + - v_right * autocvar_g_nexball_viewmodel_offset_y + - v_up * autocvar_g_nexball_viewmodel_offset_z); + v_forward * autocvar_g_nexball_viewmodel_offset.x + + v_right * autocvar_g_nexball_viewmodel_offset.y + + v_up * autocvar_g_nexball_viewmodel_offset.z); // 'safe passing' if(autocvar_g_nexball_safepass_maxdist) @@ -930,7 +939,8 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink) if(self.weaponentity.weapons) { self.weapons = self.weaponentity.weapons; - WEP_ACTION(WEP_PORTO, WR_RESETPLAYER); + Weapon w = WEP_NEXBALL; + w.wr_resetplayer(w); self.switchweapon = self.weaponentity.switchweapon; W_SwitchWeapon(self.switchweapon); @@ -942,53 +952,46 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink) nexball_setstatus(); - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(nexball_PlayerSpawn) -{ +{SELFPARAM(); self.weaponentity.weapons = '0 0 0'; if(nexball_mode & NBM_BASKETBALL) - self.weapons |= WEPSET_PORTO; + self.weapons |= WEPSET(NEXBALL); else self.weapons = '0 0 0'; - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(nexball_PlayerPhysics) -{ +{SELFPARAM(); if(self.ballcarried) { self.stat_sv_airspeedlimit_nonqw *= autocvar_g_nexball_basketball_carrier_highspeed; self.stat_sv_maxspeed *= autocvar_g_nexball_basketball_carrier_highspeed; } - return FALSE; -} - -MUTATOR_HOOKFUNCTION(nexball_SetStartItems) -{ - start_items |= IT_UNLIMITED_SUPERWEAPONS; // FIXME BAD BAD BAD BAD HACK, NEXBALL SHOULDN'T ABUSE PORTO'S WEAPON SLOT - - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing) -{ - if(self.weapon == WEP_MORTAR) - return TRUE; +{SELFPARAM(); + if(self.weapon == WEP_NEXBALL.m_id) + return true; - return FALSE; + return false; } MUTATOR_HOOKFUNCTION(nexball_FilterItem) -{ +{SELFPARAM(); if(self.classname == "droppedweapon") - if(self.weapon == WEP_MORTAR) - return TRUE; + if(self.weapon == WEP_NEXBALL.m_id) + return true; - return FALSE; + return false; } MUTATOR_DEFINITION(gamemode_nexball) @@ -999,7 +1002,6 @@ MUTATOR_DEFINITION(gamemode_nexball) MUTATOR_HOOK(PlayerSpawn, nexball_PlayerSpawn, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerPhysics, nexball_PlayerPhysics, CBC_ORDER_ANY); - MUTATOR_HOOK(SetStartItems, nexball_SetStartItems, CBC_ORDER_ANY); MUTATOR_HOOK(ForbidThrowCurrentWeapon, nexball_ForbidThrowing, CBC_ORDER_ANY); MUTATOR_HOOK(FilterItem, nexball_FilterItem, CBC_ORDER_ANY); @@ -1011,8 +1013,6 @@ MUTATOR_DEFINITION(gamemode_nexball) g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32 addstat(STAT_NB_METERSTART, AS_FLOAT, metertime); - W_Porto(WR_INIT); // abuse - // General settings /* CVTOV(g_nexball_football_boost_forward); //100 @@ -1023,10 +1023,12 @@ MUTATOR_DEFINITION(gamemode_nexball) radar_showennemies = autocvar_g_nexball_radar_showallplayers; InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE); + WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED; } MUTATOR_ONROLLBACK_OR_REMOVE { + WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED; // we actually cannot roll back nb_delayedinit here // BUT: we don't need to! If this gets called, adding always // succeeds. @@ -1034,7 +1036,7 @@ MUTATOR_DEFINITION(gamemode_nexball) MUTATOR_ONREMOVE { - print("This is a game type and it cannot be removed at runtime."); + LOG_INFO("This is a game type and it cannot be removed at runtime."); return -1; }