]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
Merge branch 'master' into terencehill/vec2_optimizations
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / gamemodes / gamemode / onslaught / sv_onslaught.qc
index a18ce34c5d06e83ad98d95a2e606f0034b5bc333..223a81f7c4d4dfb6039a3ea6b2189b0df864dfd0 100644 (file)
@@ -28,11 +28,27 @@ float autocvar_g_onslaught_spawn_choose;
 float autocvar_g_onslaught_click_radius;
 
 void FixSize(entity e);
+entity cam;
 
 // =======================
 // CaptureShield Functions
 // =======================
 
+bool clientcamera_send(entity this, entity to, int sf)
+{
+       WriteHeader(MSG_ENTITY, ENT_ONSCAMERA);
+
+       WriteCoord(MSG_ENTITY, this.origin_x);
+       WriteCoord(MSG_ENTITY, this.origin_y);
+       WriteCoord(MSG_ENTITY, this.origin_z);
+
+       WriteAngle(MSG_ENTITY, this.angles_x);
+       WriteAngle(MSG_ENTITY, this.angles_y);
+       WriteAngle(MSG_ENTITY, this.angles_z);
+
+       return true;
+}
+
 bool ons_CaptureShield_Customize(entity this, entity client)
 {
        entity e = WaypointSprite_getviewentity(client);
@@ -127,8 +143,8 @@ void onslaught_updatelinks()
        {
                l.islinked = false;
                l.isshielded = true;
-               int i;
-               for(i = 0; i < 17; ++i) { l.isgenneighbor[i] = false; l.iscpneighbor[i] = false; }
+               l.aregensneighbor = 0;
+               l.arecpsneighbor = 0;
                LOG_DEBUG(etos(l), " (point) belongs to team ", ftos(l.team));
                l.sprite.SendFlags |= 16;
        }
@@ -172,9 +188,9 @@ void onslaught_updatelinks()
                                l.enemy.isshielded = false;
                        }
                        if(l.goalentity.classname == "onslaught_generator")
-                               l.enemy.isgenneighbor[l.goalentity.team] = true;
+                               l.enemy.aregensneighbor |= BIT(l.goalentity.team);
                        else
-                               l.enemy.iscpneighbor[l.goalentity.team] = true;
+                               l.enemy.arecpsneighbor |= BIT(l.goalentity.team);
                }
                if (l.enemy.islinked)
                {
@@ -184,9 +200,9 @@ void onslaught_updatelinks()
                                l.goalentity.isshielded = false;
                        }
                        if(l.enemy.classname == "onslaught_generator")
-                               l.goalentity.isgenneighbor[l.enemy.team] = true;
+                               l.goalentity.aregensneighbor |= BIT(l.enemy.team);
                        else
-                               l.goalentity.iscpneighbor[l.enemy.team] = true;
+                               l.goalentity.arecpsneighbor |= BIT(l.enemy.team);
                }
        }
        // now update the generators
@@ -312,8 +328,8 @@ void ons_DelayedLinkSetup(entity this)
 
 int ons_ControlPoint_CanBeLinked(entity cp, int teamnumber)
 {
-       if(cp.isgenneighbor[teamnumber]) { return 2; }
-       if(cp.iscpneighbor[teamnumber]) { return 1; }
+       if(cp.aregensneighbor & BIT(teamnumber)) return 2;
+       if(cp.arecpsneighbor & BIT(teamnumber)) return 1;
 
        return 0;
 }
@@ -537,7 +553,7 @@ void ons_ControlPoint_Icon_BuildThink(entity this)
                if(IS_PLAYER(this.owner.ons_toucher))
                {
                        Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ONSLAUGHT_CAPTURE, this.owner.ons_toucher.netname, this.owner.message);
-                       Send_Notification(NOTIF_ALL_EXCEPT, this.owner.ons_toucher, MSG_CENTER, APP_TEAM_NUM(this.owner.ons_toucher.team, CENTER_ONS_CAPTURE), this.owner.message);
+                       Send_Notification(NOTIF_ALL_EXCEPT, this.owner.ons_toucher, MSG_CENTER, APP_TEAM_NUM(this.owner.ons_toucher.team, CENTER_ONS_CAPTURE_TEAM), this.owner.message);
                        Send_Notification(NOTIF_ONE, this.owner.ons_toucher, MSG_CENTER, CENTER_ONS_CAPTURE, this.owner.message);
                        PlayerScore_Add(this.owner.ons_toucher, SP_ONS_CAPS, 1);
                        PlayerTeamScore_AddScore(this.owner.ons_toucher, 10);
@@ -817,11 +833,46 @@ void ons_Generator_UpdateSprite(entity e)
        }
 }
 
+void ons_camSetup(entity this)
+{
+       vector dir;
+       vector ang = '0 0 0';
+       vector best_ang = '0 0 0';
+       float best_trace_fraction = 0;
+       while(ang.y < 360)
+       {
+               dir = vec2(cos(ang.y * DEG2RAD), sin(ang.y * DEG2RAD));
+               dir *= 500;
+               traceline(this.origin, this.origin - dir, MOVE_WORLDONLY, this);
+               if(trace_fraction > best_trace_fraction)
+               {
+                       best_trace_fraction = trace_fraction;
+                       best_ang = ang;
+                       if(trace_fraction == 1)
+                               break;
+               }
+               ang.y += 90;
+               if(ang.y == 360)
+                       ang.y = 45;
+       }
+       cam.origin = this.origin;
+       setorigin(cam, cam.origin);
+       cam.angles = best_ang;
+       Net_LinkEntity(cam, false, 0, clientcamera_send);
+
+       FOREACH_CLIENT(true, it.clientcamera = cam;);
+
+       WriteByte(MSG_ALL, SVC_SETVIEWANGLES);
+       WriteAngle(MSG_ALL, cam.angles_x);
+       WriteAngle(MSG_ALL, cam.angles_y);
+       WriteAngle(MSG_ALL, cam.angles_z);
+}
+
 void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
-       if(damage <= 0) { return; }
-       if(warmup_stage || gameover) { return; }
-       if(!round_handler_IsRoundStarted()) { return; }
+       if(damage <= 0) return;
+       if(warmup_stage || game_stopped) return;
+       if(!round_handler_IsRoundStarted()) return;
 
        if (attacker != this)
        {
@@ -877,6 +928,8 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d
                //WaypointSprite_Kill(this.sprite); // can't do this yet, code too poor
 
                onslaught_updatelinks();
+
+               ons_camSetup(this);
        }
 
        // Throw some flaming gibs on damage, more damage = more chance for gib
@@ -902,7 +955,7 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d
 void ons_GeneratorThink(entity this)
 {
        this.nextthink = time + GEN_THINKRATE;
-       if (!gameover)
+       if (!game_stopped)
        {
                if(!this.isshielded && this.wait < time)
                {
@@ -926,7 +979,8 @@ void ons_GeneratorReset(entity this)
        this.lasthealth = this.max_health = this.health = autocvar_g_onslaught_gen_health;
        this.takedamage = DAMAGE_AIM;
        this.bot_attack = true;
-       IL_PUSH(g_bot_targets, this);
+       if(!IL_CONTAINS(g_bot_targets, this))
+               IL_PUSH(g_bot_targets, this);
        this.iscaptured = true;
        this.islinked = true;
        this.isshielded = true;
@@ -985,6 +1039,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        gen.classname = "onslaught_generator";
        gen.solid = SOLID_BBOX;
        gen.team_saved = teamnumber;
+       IL_PUSH(g_saved_team, gen);
        set_movetype(gen, MOVETYPE_NONE);
        gen.lasthealth = gen.max_health = gen.health = autocvar_g_onslaught_gen_health;
        gen.takedamage = DAMAGE_AIM;
@@ -1141,6 +1196,7 @@ bool Onslaught_CheckWinner()
                nades_Clear(it);
        });
 
+       game_stopped = true;
        return 1;
 }
 
@@ -1252,7 +1308,7 @@ void havocbot_goalrating_ons_controlpoints_attack(entity this, float ratingscale
                        continue;
 
                // Ignore owned controlpoints
-               if(!(cp2.isgenneighbor[this.team] || cp2.iscpneighbor[this.team]))
+               if(!((cp2.aregensneighbor & BIT(this.team)) || (cp2.arecpsneighbor & BIT(this.team))))
                        continue;
 
                // Count team mates interested in this control point
@@ -1584,7 +1640,7 @@ bool ons_Teleport(entity player, entity tele_target, float range, bool tele_effe
 
                loc += tele_target.origin + '0 0 128' * iteration_scale;
 
-               tracebox(loc, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), loc, MOVE_NORMAL, player);
+               tracebox(loc, STAT(PL_MIN, player), STAT(PL_MAX, player), loc, MOVE_NORMAL, player);
                if(trace_fraction == 1.0 && !trace_startsolid)
                {
                        traceline(tele_target.origin, loc, MOVE_NOMONSTERS, tele_target); // double check to make sure we're not spawning outside the NULL
@@ -1621,6 +1677,7 @@ MUTATOR_HOOKFUNCTION(ons, reset_map_global)
                STAT(ROUNDLOST, it) = false;
                it.ons_deathloc = '0 0 0';
                PutClientInServer(it);
+               it.clientcamera = it;
        });
        return false;
 }
@@ -1702,7 +1759,7 @@ MUTATOR_HOOKFUNCTION(ons, PlayerSpawn)
                                iteration_scale -= i / 10;
                                loc = closest_target.origin + '0 0 96' * iteration_scale;
                                loc += ('0 1 0' * random()) * 128 * iteration_scale;
-                               tracebox(loc, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), loc, MOVE_NORMAL, player);
+                               tracebox(loc, STAT(PL_MIN, player), STAT(PL_MAX, player), loc, MOVE_NORMAL, player);
                                if(trace_fraction == 1.0 && !trace_startsolid)
                                {
                                        traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the NULL
@@ -1753,7 +1810,7 @@ MUTATOR_HOOKFUNCTION(ons, PlayerSpawn)
                                iteration_scale -= i / 10;
                                loc = closest_target.origin + '0 0 128' * iteration_scale;
                                loc += ('0 1 0' * random()) * 256 * iteration_scale;
-                               tracebox(loc, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), loc, MOVE_NORMAL, player);
+                               tracebox(loc, STAT(PL_MIN, player), STAT(PL_MAX, player), loc, MOVE_NORMAL, player);
                                if(trace_fraction == 1.0 && !trace_startsolid)
                                {
                                        traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the NULL
@@ -1966,7 +2023,7 @@ MUTATOR_HOOKFUNCTION(ons, SV_ParseClientCommand)
 
 MUTATOR_HOOKFUNCTION(ons, PlayerUseKey)
 {
-       if(MUTATOR_RETURNVALUE || gameover) { return false; }
+       if(MUTATOR_RETURNVALUE || game_stopped) return false;
 
        entity player = M_ARGV(0, entity);
 
@@ -2137,5 +2194,7 @@ void ons_Initialize()
        g_onslaught = true;
        ons_captureshield_force = autocvar_g_onslaught_shield_force;
 
+       cam = new(objective_camera);
+
        InitializeEntity(NULL, ons_DelayedInit, INITPRIO_GAMETYPE);
 }