From e9e91f9bc18dd5002e60c595c83cb8f45068a14b Mon Sep 17 00:00:00 2001 From: TimePath Date: Thu, 29 Oct 2015 18:04:31 +1100 Subject: [PATCH] Entity debugger --- qcsrc/client/announcer.qc | 13 +- qcsrc/client/commands/cl_cmd.qc | 4 +- qcsrc/client/csqcmodel_hooks.qc | 9 +- qcsrc/client/damage.qc | 5 +- qcsrc/client/generator.qc | 4 +- qcsrc/client/gibs.qc | 36 ++-- qcsrc/client/gibs.qh | 2 - qcsrc/client/hud.qh | 1 + qcsrc/client/main.qc | 173 ++++++++++-------- qcsrc/client/mapvoting.qc | 1 + qcsrc/client/miscfunctions.qc | 3 +- qcsrc/client/modeleffects.qc | 7 +- qcsrc/client/rubble.qc | 3 +- qcsrc/client/shownames.qc | 3 +- qcsrc/client/tuba.qc | 6 +- qcsrc/client/view.qc | 20 +- qcsrc/common/constants.qh | 5 +- qcsrc/common/deathtypes/all.qh | 1 + qcsrc/common/debug.qh | 111 +++++++++++ qcsrc/common/effects/all.qc | 54 +++--- qcsrc/common/effects/all.qh | 4 +- qcsrc/common/effects/effect.qh | 1 + .../gamemodes/gamemode/nexball/nexball.qc | 7 +- qcsrc/common/items/inventory.qh | 3 +- qcsrc/common/minigames/cl_minigames.qh | 4 +- qcsrc/common/minigames/minigame/nmm.qc | 3 +- qcsrc/common/minigames/minigame/ttt.qc | 3 +- qcsrc/common/minigames/sv_minigames.qc | 6 +- qcsrc/common/minigames/sv_minigames.qh | 4 +- qcsrc/common/monsters/monster/shambler.qc | 3 +- qcsrc/common/monsters/monster/spider.qc | 3 +- qcsrc/common/monsters/sv_monsters.qc | 3 +- .../common/mutators/mutator/waypoints/all.qh | 2 +- .../mutator/waypoints/waypointsprites.qc | 1 + qcsrc/common/nades/all.qc | 2 +- qcsrc/common/net_notice.qc | 4 +- qcsrc/common/notifications.qc | 9 +- qcsrc/common/triggers/func/bobbing.qc | 3 +- qcsrc/common/triggers/func/door.qc | 3 +- qcsrc/common/triggers/func/fourier.qc | 3 +- qcsrc/common/triggers/func/pendulum.qc | 3 +- qcsrc/common/triggers/func/vectormamamam.qc | 3 +- qcsrc/common/triggers/subs.qc | 3 +- qcsrc/common/triggers/trigger/jumppads.qc | 2 +- qcsrc/common/triggers/triggers.qc | 3 +- qcsrc/common/turrets/cl_turrets.qc | 3 +- qcsrc/common/turrets/sv_turrets.qc | 7 +- qcsrc/common/turrets/turret/walker.qc | 3 +- qcsrc/common/turrets/util.qc | 15 +- qcsrc/common/util.qc | 4 +- qcsrc/common/vehicles/sv_vehicles.qc | 14 +- qcsrc/common/vehicles/vehicle/bumblebee.qc | 8 +- qcsrc/common/vehicles/vehicle/raptor.qc | 12 +- qcsrc/common/weapons/weapon/arc.qc | 3 +- qcsrc/common/weapons/weapon/blaster.qc | 3 +- qcsrc/common/weapons/weapon/crylink.qc | 9 +- qcsrc/common/weapons/weapon/electro.qc | 6 +- qcsrc/common/weapons/weapon/fireball.qc | 6 +- qcsrc/common/weapons/weapon/hagar.qc | 9 +- qcsrc/common/weapons/weapon/hlac.qc | 6 +- qcsrc/common/weapons/weapon/minelayer.qc | 3 +- qcsrc/common/weapons/weapon/mortar.qc | 6 +- qcsrc/common/weapons/weapon/porto.qc | 3 +- qcsrc/common/weapons/weapon/seeker.qc | 12 +- qcsrc/common/weapons/weapon/shockwave.qc | 4 +- qcsrc/common/weapons/weapon/shotgun.qc | 4 +- qcsrc/common/weapons/weapon/vaporizer.qc | 6 +- qcsrc/lib/defer.qh | 6 +- qcsrc/lib/net.qh | 24 ++- qcsrc/lib/oo.qh | 22 ++- qcsrc/lib/sortlist.qc | 4 +- qcsrc/lib/spawnfunc.qh | 7 + qcsrc/lib/urllib.qc | 21 +-- qcsrc/lib/warpzone/client.qc | 5 +- qcsrc/lib/warpzone/common.qc | 36 +--- qcsrc/lib/warpzone/server.qc | 3 +- qcsrc/menu/xonotic/serverlist.qc | 4 +- qcsrc/server/bot/aim.qc | 4 +- qcsrc/server/bot/scripting.qc | 5 +- qcsrc/server/bot/waypoints.qc | 4 +- qcsrc/server/cheats.qc | 30 +-- qcsrc/server/cl_client.qc | 17 +- qcsrc/server/cl_player.qc | 3 +- qcsrc/server/command/radarmap.qc | 3 +- qcsrc/server/command/sv_cmd.qc | 3 +- qcsrc/server/command/vote.qc | 3 +- qcsrc/server/constants.qh | 2 - qcsrc/server/ent_cs.qc | 1 + qcsrc/server/g_damage.qc | 18 +- qcsrc/server/g_models.qc | 8 +- qcsrc/server/g_violence.qc | 27 +-- qcsrc/server/g_world.qc | 13 +- qcsrc/server/ipban.qc | 4 +- qcsrc/server/miscfunctions.qc | 7 +- qcsrc/server/mutators/mutator/gamemode_ctf.qc | 3 +- .../mutators/mutator/gamemode_keepaway.qc | 4 +- .../mutators/mutator/gamemode_keyhunt.qc | 3 +- .../mutators/mutator/gamemode_onslaught.qc | 6 +- .../server/mutators/mutator/mutator_nades.qc | 14 +- .../mutators/mutator/mutator_overkill.qc | 9 +- qcsrc/server/mutators/mutator/sandbox.qc | 3 +- qcsrc/server/pathlib/main.qc | 3 +- qcsrc/server/portals.qc | 3 +- qcsrc/server/scores.qc | 13 +- qcsrc/server/spawnpoints.qc | 4 +- qcsrc/server/steerlib.qc | 8 +- qcsrc/server/sv_main.qc | 1 + qcsrc/server/weapons/accuracy.qc | 1 + qcsrc/server/weapons/throwing.qc | 3 +- qcsrc/server/weapons/weaponsystem.qc | 9 +- 110 files changed, 537 insertions(+), 526 deletions(-) create mode 100644 qcsrc/common/debug.qh diff --git a/qcsrc/client/announcer.qc b/qcsrc/client/announcer.qc index 2ad1c67c1..a2e13be53 100644 --- a/qcsrc/client/announcer.qc +++ b/qcsrc/client/announcer.qc @@ -78,19 +78,18 @@ void Announcer_Gamestart() { if(time < startTime) { - entity e = find(world, classname, "announcer_countdown"); - if (!e) + static entity announcer_countdown; + if (!announcer_countdown) { - e = spawn(); - e.classname = "announcer_countdown"; - e.think = Announcer_Countdown; + announcer_countdown = new(announcer_countdown); + announcer_countdown.think = Announcer_Countdown; } if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle - if(time > e.nextthink) // don't play it again if countdown was already going + if(time > announcer_countdown.nextthink) // don't play it again if countdown was already going Local_Notification(MSG_ANNCE, ANNCE_PREPARE); - e.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime + announcer_countdown.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime } } diff --git a/qcsrc/client/commands/cl_cmd.qc b/qcsrc/client/commands/cl_cmd.qc index db4d59a5c..489e86c61 100644 --- a/qcsrc/client/commands/cl_cmd.qc +++ b/qcsrc/client/commands/cl_cmd.qc @@ -172,15 +172,13 @@ void LocalCommand_debugmodel(int request, int argc) case CMD_REQUEST_COMMAND: { string modelname = argv(1); - entity debugmodel_entity; - debugmodel_entity = spawn(); + entity debugmodel_entity = new(debugmodel); precache_model(modelname); _setmodel(debugmodel_entity, modelname); setorigin(debugmodel_entity, view_origin); debugmodel_entity.angles = view_angles; debugmodel_entity.draw = DrawDebugModel; - debugmodel_entity.classname = "debugmodel"; return; } diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index e2e0e9341..e7a6a6bb3 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -136,8 +136,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer) // which one is ALWAYS good? if (!forceplayermodels_goodmodel) { - entity e; - e = spawn(); + entity e = spawn(); precache_model(cvar_defstring("_cl_playermodel")); _setmodel(e, cvar_defstring("_cl_playermodel")); forceplayermodels_goodmodel = e.model; @@ -168,8 +167,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer) forceplayermodels_attempted = 1; // only if this failed, find it out on our own - entity e; - e = spawn(); + entity e = spawn(); _setmodel(e, autocvar__cl_playermodel); // this is harmless, see below forceplayermodels_modelisgoodmodel = fexists(e.model); forceplayermodels_model = e.model; @@ -180,8 +178,7 @@ void CSQCPlayer_ModelAppearance_Apply(bool islocalplayer) if(autocvar_cl_forcemyplayermodel != "" && autocvar_cl_forcemyplayermodel != forceplayermodels_mymodel) { - entity e; - e = spawn(); + entity e = spawn(); _setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below forceplayermodels_myisgoodmodel = fexists(e.model); forceplayermodels_mymodel = e.model; diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 34890e034..2d7c4f2c1 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -105,10 +105,10 @@ void DamageEffect(vector hitorg, float thedamage, int type, int specnum) else { return; } // objects don't bleed } - e = spawn(); + e = new(damage); + make_pure(e); setmodel(e, MDL_Null); // necessary to attach and read origin setattachment(e, self, gettaginfo_name); // attach to the given bone - e.classname = "damage"; e.owner = self; e.cnt = time + life; e.team = _particleeffectnum(effectname); @@ -119,6 +119,7 @@ void DamageEffect(vector hitorg, float thedamage, int type, int specnum) void Ent_DamageInfo(float isNew) {SELFPARAM(); + make_pure(this); float thedamage, rad, edge, thisdmg; bool hitplayer = false; int species, forcemul; diff --git a/qcsrc/client/generator.qc b/qcsrc/client/generator.qc index d7114d1bf..226d13dc3 100644 --- a/qcsrc/client/generator.qc +++ b/qcsrc/client/generator.qc @@ -32,9 +32,7 @@ void ons_generator_ray_draw(entity this) void ons_generator_ray_spawn(vector org) { - entity e; - e = spawn(); - e.classname = "ons_ray"; + entity e = new(ons_ray); setmodel(e, MDL_ONS_RAY); setorigin(e, org); e.angles = randomvec() * 360; diff --git a/qcsrc/client/gibs.qc b/qcsrc/client/gibs.qc index 4afa5eb88..5c5e69f1f 100644 --- a/qcsrc/client/gibs.qc +++ b/qcsrc/client/gibs.qc @@ -123,7 +123,6 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector // TODO remove some gibs according to cl_nogibs gib = RubbleNew("gib"); - gib.classname = "gib"; gib.move_movetype = MOVETYPE_BOUNCE; gib.gravity = 1; gib.solid = SOLID_CORPSE; @@ -159,23 +158,19 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector RubbleLimit("gib", autocvar_cl_gibs_maxcount, Gib_Delete); } -void Ent_GibSplash(bool isNew) -{SELFPARAM(); - int amount, type, specnum; - vector org, vel; - string specstr; - bool issilent; - string gentle_prefix = "morphed_"; +REGISTER_NET_TEMP(net_gibsplash, bool isNew) +{ + Net_Accept(net_gibsplash); - float randomvalue; - int c; + string gentle_prefix = "morphed_"; - type = ReadByte(); // gibbage type - amount = ReadByte() / 16.0; // gibbage amount + int type = ReadByte(); // gibbage type + int amount = ReadByte() / 16.0; // gibbage amount + vector org; org.x = ReadShort() * 4 + 2; org.y = ReadShort() * 4 + 2; org.z = ReadShort() * 4 + 2; - vel = decompressShortVector(ReadShort()); + vector vel = decompressShortVector(ReadShort()); float cl_gentle_gibs = autocvar_cl_gentle_gibs; if(cl_gentle_gibs || autocvar_cl_gentle) @@ -203,18 +198,18 @@ void Ent_GibSplash(bool isNew) if(amount <= 0 || !isNew) return; - setorigin(self, org); // for the sounds + setorigin(this, org); // for the sounds - specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5) - issilent = (type & 0x40); + int specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5) + bool issilent = (type & 0x40); type = type & 0x87; // remove the species bits: bit 7 = gentle, bit 0,1,2 = kind of gib - specstr = species_prefix(specnum); + string specstr = species_prefix(specnum); switch(type) { case 0x01: if(!issilent) - sound (self, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM); + sound (this, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM); if(prandom() < amount) TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent); @@ -222,9 +217,9 @@ void Ent_GibSplash(bool isNew) if(prandom() < amount) TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent); - for(c = 0; c < amount; ++c) + for(int c = 0; c < amount; ++c) { - randomvalue = amount - c; + int randomvalue = amount - c; if(prandom() < randomvalue) TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent); @@ -267,4 +262,5 @@ void Ent_GibSplash(bool isNew) // no gibs in gentle mode, sorry break; } + remove(this); } diff --git a/qcsrc/client/gibs.qh b/qcsrc/client/gibs.qh index eb63aa1fe..69058f6c4 100644 --- a/qcsrc/client/gibs.qh +++ b/qcsrc/client/gibs.qh @@ -21,6 +21,4 @@ void Gib_Draw(entity this); void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector vrand, int specnum, bool destroyontouch, bool issilent); -void Ent_GibSplash(bool isNew); - #endif diff --git a/qcsrc/client/hud.qh b/qcsrc/client/hud.qh index ba9cb171e..cbdfb0c47 100644 --- a/qcsrc/client/hud.qh +++ b/qcsrc/client/hud.qh @@ -12,6 +12,7 @@ REGISTER_REGISTRY(Registerhud_panels) #define REGISTER_HUD_PANEL(id, draw_func, name, configflags, showflags) \ void draw_func(); \ REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \ + make_pure(this); \ this.panel_id = this.m_id; \ this.panel_draw = draw_func; \ this.panel_name = #name; \ diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 9d20c4061..fd5da629d 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -42,8 +42,7 @@ void clearentity(entity e) { if (!clearentity_ent) { - clearentity_ent = spawn(); - clearentity_ent.classname = "clearentity"; + clearentity_ent = new(clearentity); } int n = e.entnum; copyentity(clearentity_ent, e); @@ -297,7 +296,10 @@ void Playerchecker_Think() { // player connected if (!e) - playerslots[i] = e = spawn(); + { + playerslots[i] = e = new(playerslot); + make_pure(e); + } e.sv_entnum = i; e.ping = 0; e.ping_packetloss = 0; @@ -316,8 +318,8 @@ void Porto_Init(); void TrueAim_Init(); void PostInit(void) { - entity playerchecker; - playerchecker = spawn(); + entity playerchecker = new(playerchecker); + make_pure(playerchecker); playerchecker.think = Playerchecker_Think; playerchecker.nextthink = time + 0.2; @@ -373,8 +375,9 @@ void Ent_RemoveEntCS() } void Ent_ReadEntCS() {SELFPARAM(); + make_pure(this); + this.classname = "entcs_receiver"; InterpolateOrigin_Undo(); - self.classname = "entcs_receiver"; int sf = ReadByte(); if(sf & BIT(0)) @@ -418,6 +421,7 @@ void Ent_RemovePlayerScore() void Ent_ReadPlayerScore() {SELFPARAM(); + make_pure(this); int i, n; bool isNew; entity o; @@ -440,9 +444,13 @@ void Ent_ReadPlayerScore() self.sv_entnum = n; - if (!(playerslots[self.sv_entnum])) - playerslots[self.sv_entnum] = spawn(); - o = self.owner = playerslots[self.sv_entnum]; + o = playerslots[self.sv_entnum]; + if (!o) + { + o = playerslots[self.sv_entnum] = new(playerslot); + make_pure(o); + } + self.owner = o; o.sv_entnum = self.sv_entnum; o.gotscores = 1; @@ -476,6 +484,7 @@ void Ent_ReadPlayerScore() void Ent_ReadTeamScore() {SELFPARAM(); + make_pure(this); int i; entity o; @@ -505,6 +514,7 @@ void Ent_ReadTeamScore() void Ent_ClientData() { + make_pure(self); float newspectatee_status; int f = ReadByte(); @@ -554,6 +564,7 @@ void Ent_ClientData() void Ent_Nagger() { + make_pure(self); int i, j, b, f; int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS @@ -609,6 +620,7 @@ void Ent_Nagger() void Ent_EliminatedPlayers() { + make_pure(self); int i, j, b, f; int sf = ReadByte(); @@ -630,14 +642,15 @@ void Ent_EliminatedPlayers() void Ent_RandomSeed() { - float s; + make_pure(self); prandom_debug(); - s = ReadShort(); + float s = ReadShort(); psrandom(s); } void Ent_ReadAccuracy() { + make_pure(self); int sf = ReadInt24_t(); if (sf == 0) { for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) @@ -768,11 +781,12 @@ void Ent_RadarLink(); void Ent_Init(); void Ent_ScoresInfo(); void CSQC_Ent_Update(float bIsNewEntity) -{SELFPARAM(); +{ + SELFPARAM(); int t = ReadByte(); if(autocvar_developer_csqcentities) - LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t); + LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, this, this.entnum, this.enttype, t); // set up the "time" global for received entities to be correct for interpolation purposes float savetime = time; @@ -788,13 +802,13 @@ void CSQC_Ent_Update(float bIsNewEntity) } #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED - if(self.enttype) + if(this.enttype) { - if(t != self.enttype || bIsNewEntity) + if(t != this.enttype || bIsNewEntity) { - LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t); + LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(this), this.entnum, this.enttype, t); Ent_Remove(); - clearentity(self); + clearentity(this); bIsNewEntity = 1; } } @@ -802,84 +816,83 @@ void CSQC_Ent_Update(float bIsNewEntity) { if(!bIsNewEntity) { - LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t); + LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(this), this.entnum, t); bIsNewEntity = 1; } } #endif - self.enttype = t; + this.enttype = t; bool done = false; FOREACH(LinkedEntities, it.m_id == t, LAMBDA( - it.m_read(self, bIsNewEntity); + it.m_read(this, bIsNewEntity); done = true; break; )); if (!done) switch(t) { - case ENT_CLIENT_MUTATOR: { + #define HANDLE(t) case t: this.classname = #t; this.sourceLocFile = __FILE__; this.sourceLocLine = __LINE__; + HANDLE(ENT_CLIENT_MUTATOR) { int mutID = ReadMutator(); if (!MUTATOR_CALLHOOK(CSQC_Ent_Update, mutID, bIsNewEntity)) - error(sprintf("Unknown mutator type in CSQC_Ent_Update (mutID: %d, edict: %d, classname: %s)\n", mutID, num_for_edict(self), self.classname)); + error(sprintf("Unknown mutator type in CSQC_Ent_Update (mutID: %d, edict: %d, classname: %s)\n", mutID, num_for_edict(this), this.classname)); break; } - case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break; - case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break; - case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break; - case ENT_CLIENT_POINTPARTICLES: Ent_PointParticles(); break; - case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break; - case ENT_CLIENT_LASER: Ent_Laser(); break; - case ENT_CLIENT_NAGGER: Ent_Nagger(); break; - case ENT_CLIENT_ELIMINATEDPLAYERS: Ent_EliminatedPlayers(); break; - case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break; - case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break; - case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(bIsNewEntity); break; - case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(bIsNewEntity); break; - case ENT_CLIENT_INIT: Ent_Init(); break; - case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break; - case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break; - case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break; - case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break; - case ENT_CLIENT_WALL: Ent_Wall(); break; - case ENT_CLIENT_MODELEFFECT: Ent_ModelEffect(bIsNewEntity); break; - case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break; - case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break; - case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break; - case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break; - case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break; - case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break; - case ENT_CLIENT_INVENTORY: Inventory_Read(self); break; - case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break; - case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break; - case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break; - case ENT_CLIENT_TURRET: ent_turret(); break; - case ENT_CLIENT_GENERATOR: ent_generator(); break; - case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(this); break; - case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break; - case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break; - case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break; - case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break; - case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break; - case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break; - case ENT_CLIENT_MINIGAME: ent_read_minigame(); break; - case ENT_CLIENT_VIEWLOC: ent_viewloc(); break; - case ENT_CLIENT_VIEWLOC_TRIGGER: ent_viewloc_trigger(); break; - case ENT_CLIENT_LADDER: ent_func_ladder(); break; - case ENT_CLIENT_TRIGGER_PUSH: ent_trigger_push(); break; - case ENT_CLIENT_TARGET_PUSH: ent_target_push(); break; - case ENT_CLIENT_CONVEYOR: ent_conveyor(); break; - case ENT_CLIENT_DOOR: ent_door(); break; - case ENT_CLIENT_PLAT: ent_plat(); break; - case ENT_CLIENT_SWAMP: ent_swamp(); break; - case ENT_CLIENT_CORNER: ent_corner(); break; - case ENT_CLIENT_KEYLOCK: ent_keylock(); break; - case ENT_CLIENT_TRAIN: ent_train(); break; - case ENT_CLIENT_TRIGGER_IMPULSE: ent_trigger_impulse(); break; - case ENT_CLIENT_EFFECT: Read_Effect(bIsNewEntity); break; - + HANDLE(ENT_CLIENT_ENTCS) Ent_ReadEntCS(); break; + HANDLE(ENT_CLIENT_SCORES) Ent_ReadPlayerScore(); break; + HANDLE(ENT_CLIENT_TEAMSCORES) Ent_ReadTeamScore(); break; + HANDLE(ENT_CLIENT_POINTPARTICLES) Ent_PointParticles(); break; + HANDLE(ENT_CLIENT_RAINSNOW) Ent_RainOrSnow(); break; + HANDLE(ENT_CLIENT_LASER) Ent_Laser(); break; + HANDLE(ENT_CLIENT_NAGGER) Ent_Nagger(); break; + HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS) Ent_EliminatedPlayers(); break; + HANDLE(ENT_CLIENT_RADARLINK) Ent_RadarLink(); break; + HANDLE(ENT_CLIENT_PROJECTILE) Ent_Projectile(); break; + HANDLE(ENT_CLIENT_DAMAGEINFO) Ent_DamageInfo(bIsNewEntity); break; + HANDLE(ENT_CLIENT_INIT) Ent_Init(); break; + HANDLE(ENT_CLIENT_SCORES_INFO) Ent_ScoresInfo(); break; + HANDLE(ENT_CLIENT_MAPVOTE) Ent_MapVote(); break; + HANDLE(ENT_CLIENT_CLIENTDATA) Ent_ClientData(); break; + HANDLE(ENT_CLIENT_RANDOMSEED) Ent_RandomSeed(); break; + HANDLE(ENT_CLIENT_WALL) Ent_Wall(); break; + HANDLE(ENT_CLIENT_MODELEFFECT) Ent_ModelEffect(bIsNewEntity); break; + HANDLE(ENT_CLIENT_TUBANOTE) Ent_TubaNote(bIsNewEntity); break; + HANDLE(ENT_CLIENT_WARPZONE) WarpZone_Read(bIsNewEntity); break; + HANDLE(ENT_CLIENT_WARPZONE_CAMERA) WarpZone_Camera_Read(bIsNewEntity); break; + HANDLE(ENT_CLIENT_WARPZONE_TELEPORTED) WarpZone_Teleported_Read(bIsNewEntity); break; + HANDLE(ENT_CLIENT_TRIGGER_MUSIC) Ent_ReadTriggerMusic(); break; + HANDLE(ENT_CLIENT_HOOK) Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break; + HANDLE(ENT_CLIENT_INVENTORY) Inventory_Read(this); break; + HANDLE(ENT_CLIENT_ARC_BEAM) Ent_ReadArcBeam(bIsNewEntity); break; + HANDLE(ENT_CLIENT_ACCURACY) Ent_ReadAccuracy(); break; + HANDLE(ENT_CLIENT_AUXILIARYXHAIR) Net_AuXair2(bIsNewEntity); break; + HANDLE(ENT_CLIENT_TURRET) ent_turret(); break; + HANDLE(ENT_CLIENT_GENERATOR) ent_generator(); break; + HANDLE(ENT_CLIENT_CONTROLPOINT_ICON) ent_cpicon(this); break; + HANDLE(ENT_CLIENT_MODEL) CSQCModel_Read(bIsNewEntity); break; + HANDLE(ENT_CLIENT_ITEM) ItemRead(bIsNewEntity); break; + HANDLE(ENT_CLIENT_BUMBLE_RAYGUN) bumble_raygun_read(bIsNewEntity); break; + HANDLE(ENT_CLIENT_SPAWNPOINT) Ent_ReadSpawnPoint(bIsNewEntity); break; + HANDLE(ENT_CLIENT_SPAWNEVENT) Ent_ReadSpawnEvent(bIsNewEntity); break; + HANDLE(ENT_CLIENT_NOTIFICATION) Read_Notification(bIsNewEntity); break; + HANDLE(ENT_CLIENT_MINIGAME) ent_read_minigame(); break; + HANDLE(ENT_CLIENT_VIEWLOC) ent_viewloc(); break; + HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER) ent_viewloc_trigger(); break; + HANDLE(ENT_CLIENT_LADDER) ent_func_ladder(); break; + HANDLE(ENT_CLIENT_TRIGGER_PUSH) ent_trigger_push(); break; + HANDLE(ENT_CLIENT_TARGET_PUSH) ent_target_push(); break; + HANDLE(ENT_CLIENT_CONVEYOR) ent_conveyor(); break; + HANDLE(ENT_CLIENT_DOOR) ent_door(); break; + HANDLE(ENT_CLIENT_PLAT) ent_plat(); break; + HANDLE(ENT_CLIENT_SWAMP) ent_swamp(); break; + HANDLE(ENT_CLIENT_CORNER) ent_corner(); break; + HANDLE(ENT_CLIENT_KEYLOCK) ent_keylock(); break; + HANDLE(ENT_CLIENT_TRAIN) ent_train(); break; + HANDLE(ENT_CLIENT_TRIGGER_IMPULSE) ent_trigger_impulse(); break; + #undef HANDLE default: - //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype)); - error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", self.enttype, num_for_edict(self), self.classname)); + //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), this.enttype)); + error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", this.enttype, num_for_edict(this), this.classname)); break; } @@ -978,7 +991,7 @@ void Gamemode_Init(); void Ent_ScoresInfo() {SELFPARAM(); int i; - self.classname = "ent_client_scores_info"; + make_pure(this); gametype = ReadInt24_t(); HUD_ModIcons_SetFunc(); for(i = 0; i < MAX_SCORE; ++i) @@ -1001,7 +1014,7 @@ void Ent_ScoresInfo() void Ent_Init() {SELFPARAM(); - self.classname = "ent_client_init"; + make_pure(this); nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th diff --git a/qcsrc/client/mapvoting.qc b/qcsrc/client/mapvoting.qc index 21bb421a9..20ff10058 100644 --- a/qcsrc/client/mapvoting.qc +++ b/qcsrc/client/mapvoting.qc @@ -853,6 +853,7 @@ void MapVote_UpdateVotes() void Ent_MapVote() { + make_pure(self); int sf = ReadByte(); if(sf & 1) diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 7983e740f..036c9570f 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -123,7 +123,8 @@ entity GetTeam(int Team, bool add) return teamslots[num]; if (!add) return world; - entity tm = spawn(); + entity tm = new(team); + make_pure(tm); tm.team = Team; teamslots[num] = tm; RegisterTeam(tm); diff --git a/qcsrc/client/modeleffects.qc b/qcsrc/client/modeleffects.qc index d870d81e9..c17940b94 100644 --- a/qcsrc/client/modeleffects.qc +++ b/qcsrc/client/modeleffects.qc @@ -24,13 +24,12 @@ void ModelEffect_Draw(entity this) } void Ent_ModelEffect(bool isNew) -{SELFPARAM(); - self.classname = "modeleffect_spawner"; +{ + make_pure(self); int f = ReadByte(); - entity e = spawn(); - e.classname = "modeleffect"; + entity e = new(modeleffect); e.model = "from network"; e.modelindex = ReadShort(); e.skin = ReadByte(); diff --git a/qcsrc/client/rubble.qc b/qcsrc/client/rubble.qc index 5af2e2350..3a0d3430d 100644 --- a/qcsrc/client/rubble.qc +++ b/qcsrc/client/rubble.qc @@ -45,9 +45,8 @@ void RubbleLimit(string cname, float limit, void() deleteproc) entity RubbleNew(string cname) { - entity e; // spawn a new entity and return it - e = spawn(); + entity e = spawn(); e.classname = cname; e.creationtime = time; return e; diff --git a/qcsrc/client/shownames.qc b/qcsrc/client/shownames.qc index 80a15ad38..05493e263 100644 --- a/qcsrc/client/shownames.qc +++ b/qcsrc/client/shownames.qc @@ -202,8 +202,7 @@ void Draw_ShowNames_All() e = shownames_ent[i]; if(!e) { - e = spawn(); - e.classname = "shownames_tag"; + e = new(shownames_tag); e.sv_entnum = i+1; shownames_ent[i] = e; } diff --git a/qcsrc/client/tuba.qc b/qcsrc/client/tuba.qc index ed2964936..e0613b575 100644 --- a/qcsrc/client/tuba.qc +++ b/qcsrc/client/tuba.qc @@ -118,11 +118,9 @@ void Ent_TubaNote(bool isNew) Ent_TubaNote_StopSound(); } } else { - self.enemy = spawn(); - self.enemy.classname = "tuba_note"; + self.enemy = new(tuba_note); if (Tuba_PitchStep) { - self.enemy.enemy = spawn(); - self.enemy.enemy.classname = "tuba_note_2"; + self.enemy.enemy = new(tuba_note_2); } isNew = true; } diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index c7144372a..08a281f34 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -11,6 +11,7 @@ #include "mutators/events.qh" #include "../common/constants.qh" +#include "../common/debug.qh" #include "../common/mapinfo.qh" #include "../common/gamemodes/all.qh" #include "../common/nades/all.qh" @@ -110,8 +111,8 @@ void Porto_Draw(entity this) void Porto_Init() { - porto = spawn(); - porto.classname = "porto"; + porto = new(porto); + make_pure(porto); porto.draw = Porto_Draw; porto.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP; } @@ -278,11 +279,11 @@ const float SHOTTYPE_HITENEMY = 4; void TrueAim_Init() { - trueaim = spawn(); - trueaim.classname = "trueaim"; + trueaim = new(trueaim); + make_pure(trueaim); trueaim.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - trueaim_rifle = spawn(); - trueaim_rifle.classname = "trueaim_rifle"; + trueaim_rifle = new(trueaim_rifle); + make_pure(trueaim_rifle); trueaim_rifle.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE; } @@ -1516,13 +1517,11 @@ void CSQC_UpdateView(float w, float h) if(!nightvision_noise) { - nightvision_noise = spawn(); - nightvision_noise.classname = "nightvision_noise"; + nightvision_noise = new(nightvision_noise); } if(!nightvision_noise2) { - nightvision_noise2 = spawn(); - nightvision_noise2.classname = "nightvision_noise2"; + nightvision_noise2 = new(nightvision_noise2); } // color tint in yellow @@ -1836,6 +1835,7 @@ void CSQC_UpdateView(float w, float h) WITH(entity, self, e, e.draw2d(e)); } Draw_ShowNames_All(); + Debug_Draw(); scoreboard_active = HUD_WouldDrawScoreboard(); diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 47b07fc01..b08787734 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -81,8 +81,9 @@ const int ENT_CLIENT_LASER = 8; const int ENT_CLIENT_NAGGER = 9; // flags [votecalledvote] const int ENT_CLIENT_RADARLINK = 11; // flags [startorigin] [endorigin] [startcolor+16*endcolor] const int ENT_CLIENT_PROJECTILE = 12; -const int ENT_CLIENT_GIBSPLASH = 13; + const int ENT_CLIENT_DAMAGEINFO = 14; + const int ENT_CLIENT_INIT = 16; const int ENT_CLIENT_MAPVOTE = 17; const int ENT_CLIENT_CLIENTDATA = 18; @@ -123,7 +124,7 @@ const int ENT_CLIENT_CORNER = 70; const int ENT_CLIENT_KEYLOCK = 71; const int ENT_CLIENT_GENERATOR = 72; const int ENT_CLIENT_CONTROLPOINT_ICON = 73; -const int ENT_CLIENT_EFFECT = 74; + const int ENT_CLIENT_MINIGAME = 75; const int ENT_CLIENT_VIEWLOC = 78; const int ENT_CLIENT_VIEWLOC_TRIGGER = 79; diff --git a/qcsrc/common/deathtypes/all.qh b/qcsrc/common/deathtypes/all.qh index 2bf1169bf..05548c9e1 100644 --- a/qcsrc/common/deathtypes/all.qh +++ b/qcsrc/common/deathtypes/all.qh @@ -12,6 +12,7 @@ REGISTER_REGISTRY(RegisterDeathtypes) #define REGISTER_DEATHTYPE(id, msg_death, msg_death_by, extra) \ REGISTER(RegisterDeathtypes, DEATH, Deathtypes, id, m_id, new(deathtype)) { \ + make_pure(this); \ this.m_id += DT_FIRST; \ this.nent_name = #id; \ this.death_msgextra = extra; \ diff --git a/qcsrc/common/debug.qh b/qcsrc/common/debug.qh new file mode 100644 index 000000000..0016492a7 --- /dev/null +++ b/qcsrc/common/debug.qh @@ -0,0 +1,111 @@ +#ifndef DEBUG_H +#define DEBUG_H + +.bool debug; +.int sv_entnum; +REGISTER_NET_TEMP(net_debug, bool isNew) +#ifdef CSQC + { + Net_Accept(net_debug); + this.sv_entnum = ReadShort(); + if (ReadByte()) make_pure(this); + this.origin_x = ReadCoord(); + this.origin_y = ReadCoord(); + this.origin_z = ReadCoord(); + setorigin(this, this.origin); + this.debug = true; // identify server entities by this + this.classname = strzone(ReadString()); + this.sourceLocFile = strzone(ReadString()); + this.sourceLocLine = ReadInt24_t(); + } +#endif + +#ifdef SVQC + bool debug_send(entity this, entity to, int sf) + { + int channel = MSG_ONE; + msg_entity = to; + WriteHeader(channel, net_debug); + WriteShort(channel, num_for_edict(this)); + WriteByte(channel, is_pure(this)); + WriteCoord(channel, this.origin.x); + WriteCoord(channel, this.origin.y); + WriteCoord(channel, this.origin.z); + WriteString(channel, this.classname); + WriteString(channel, this.sourceLocFile); + WriteInt24_t(channel, this.sourceLocLine); + return true; + } +#endif + +bool autocvar_debugdraw; + +#ifdef CSQC + .int debugdraw_last; + vector project_3d_to_2d(vector vec); + void Debug_Draw() + { + if (!autocvar_debugdraw) return; + static int debugdraw_frame; + ++debugdraw_frame; + const int size = 8; + for (entity e1 = NULL; (e1 = nextent(e1)); ) + { + if (e1.debugdraw_last == debugdraw_frame) continue; + int ofs = 0; + for (entity e = findradius(e1.origin, 100); e; e = e.chain) + { + if (e.debugdraw_last == debugdraw_frame) continue; + e.debugdraw_last = debugdraw_frame; + vector rgb = (e.debug) ? '0 0 1' : '1 0 0'; + if (is_pure(e)) + { + if (autocvar_debugdraw < 2) continue; + rgb.y = 1; + } + vector pos = project_3d_to_2d(e.origin); + if (pos.z < 0) continue; + pos.z = 0; + pos.y += ofs * size; + drawcolorcodedstring2(pos, + sprintf("%d: '%s'@%s:%d", (e.debug ? e.sv_entnum : num_for_edict(e)), + e.classname, e.sourceLocFile, e.sourceLocLine), + size * '1 1 0', rgb, 0.5, DRAWFLAG_NORMAL); + ++ofs; + } + } + } +#endif + +#ifdef SVQC + GENERIC_COMMAND(debugdraw_sv, "Dump all server entities") + { + switch (request) + { + case CMD_REQUEST_COMMAND: + { + if (!autocvar_debugdraw) return; + int n = 1000; + int rem = n; + for (entity e = NULL; (e = findfloat(e, debug, 0)) && rem > 0; ) + { + if (autocvar_debugdraw < 2 && is_pure(e)) continue; + debug_send(e, nextent(NULL), 0); + e.debug = true; + --rem; + } + LOG_INFOF("%d server entities sent\n", n - rem); + return; + } + + default: + case CMD_REQUEST_USAGE: + { + LOG_INFO(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " debugdraw_sv")); + return; + } + } + } +#endif + +#endif diff --git a/qcsrc/common/effects/all.qc b/qcsrc/common/effects/all.qc index e90f3c615..7172a202a 100644 --- a/qcsrc/common/effects/all.qc +++ b/qcsrc/common/effects/all.qc @@ -1,15 +1,16 @@ #include "all.qh" +REGISTER_NET_TEMP(net_effect, bool isNew) #ifdef CSQC -void Read_Effect(bool is_new) { int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte(); entity eff = Effects[net_name]; - vector v, vel = '0 0 0'; + vector vel = '0 0 0'; int eff_cnt = 1; bool eff_trail = eff.eent_eff_trail; + vector v; v_x = ReadCoord(); v_y = ReadCoord(); v_z = ReadCoord(); @@ -25,38 +26,37 @@ void Read_Effect(bool is_new) if(!eff_trail) eff_cnt = ReadByte(); - if(is_new) - { - if(eff_trail) - WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel); - else - pointparticles(particleeffectnum(eff), v, vel, eff_cnt); - } + if(eff_trail) + WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel); + else + pointparticles(particleeffectnum(eff), v, vel, eff_cnt); } #endif #ifdef SVQC bool Net_Write_Effect(entity this, entity client, int sf) { - WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT); + int channel = MSG_ONE; + msg_entity = client; + WriteHeader(channel, net_effect); (Effects_COUNT >= 255) - ? WriteShort(MSG_ENTITY, self.m_id) - : WriteByte(MSG_ENTITY, self.m_id); - WriteCoord(MSG_ENTITY, self.eent_net_location_x); - WriteCoord(MSG_ENTITY, self.eent_net_location_y); - WriteCoord(MSG_ENTITY, self.eent_net_location_z); + ? WriteShort(channel, this.m_id) + : WriteByte(channel, this.m_id); + WriteCoord(channel, this.eent_net_location_x); + WriteCoord(channel, this.eent_net_location_y); + WriteCoord(channel, this.eent_net_location_z); // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set - if(self.eent_net_velocity) + if(this.eent_net_velocity) { - WriteByte(MSG_ENTITY, true); - WriteCoord(MSG_ENTITY, self.eent_net_velocity_x); - WriteCoord(MSG_ENTITY, self.eent_net_velocity_y); - WriteCoord(MSG_ENTITY, self.eent_net_velocity_z); + WriteByte(channel, true); + WriteCoord(channel, this.eent_net_velocity_x); + WriteCoord(channel, this.eent_net_velocity_y); + WriteCoord(channel, this.eent_net_velocity_z); } - else { WriteByte(MSG_ENTITY, false); } + else { WriteByte(channel, false); } - if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); } + if(!this.eent_eff_trail) { WriteByte(channel, this.eent_net_count); } return true; } @@ -64,9 +64,9 @@ void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt) { if(!eff) { return; } if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count! - entity net_eff = spawn(); + entity net_eff = new(net_effect); + make_pure(net_eff); net_eff.owner = eff; - net_eff.classname = "net_effect"; //net_eff.eent_broadcast = broadcast; net_eff.m_id = eff.m_id; net_eff.eent_net_velocity = eff_vel; @@ -74,10 +74,8 @@ void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt) net_eff.eent_net_count = eff_cnt; net_eff.eent_eff_trail = eff.eent_eff_trail; - net_eff.think = SUB_Remove; - net_eff.nextthink = time + 0.2; // don't need to keep this long - - Net_LinkEntity(net_eff, false, 0, Net_Write_Effect); + entity e; FOR_EACH_REALCLIENT(e) Net_Write_Effect(net_eff, e, 0); + remove(net_eff); } void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt) diff --git a/qcsrc/common/effects/all.qh b/qcsrc/common/effects/all.qh index 7046af11b..83be0aa76 100644 --- a/qcsrc/common/effects/all.qh +++ b/qcsrc/common/effects/all.qh @@ -3,9 +3,7 @@ #include "effect.qh" -#ifdef CSQC -void Read_Effect(bool is_new); -#elif defined(SVQC) +#ifdef SVQC void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt); void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt); #endif diff --git a/qcsrc/common/effects/effect.qh b/qcsrc/common/effects/effect.qh index bd9cd99e5..bc8f8483e 100644 --- a/qcsrc/common/effects/effect.qh +++ b/qcsrc/common/effects/effect.qh @@ -14,6 +14,7 @@ entity Create_Effect_Entity(string eff_name, bool eff_trail) { entity this = new(effect_entity); + make_pure(this); this.eent_eff_name = eff_name; this.eent_eff_trail = eff_trail; return this; diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc index 72873b3eb..dc158a69a 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc +++ b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc @@ -451,9 +451,7 @@ spawnfunc(nexball_team) void nb_spawnteam(string teamname, float teamcolor) { LOG_TRACE("^2spawned team ", teamname, "\n"); - entity e; - e = spawn(); - e.classname = "nexball_team"; + entity e = new(nexball_team); e.netname = teamname; e.cnt = teamcolor; e.team = e.cnt + 1; @@ -804,10 +802,9 @@ void W_Nexball_Attack2(void) return; W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0); - entity missile = spawn(); + entity missile = new(ballstealer); missile.owner = self; - missile.classname = "ballstealer"; missile.movetype = MOVETYPE_FLY; PROJECTILE_MAKETRIGGER(missile); diff --git a/qcsrc/common/items/inventory.qh b/qcsrc/common/items/inventory.qh index a6d266ae5..232a4fcaf 100644 --- a/qcsrc/common/items/inventory.qh +++ b/qcsrc/common/items/inventory.qh @@ -14,6 +14,7 @@ class(Inventory) .int inv_items[Items_MAX]; #ifdef CSQC void Inventory_Read(Inventory data) { + make_pure(self); const int bits = ReadInt24_t(); FOREACH(Items, bits & BIT(it.m_id), LAMBDA( .int fld = inv_items[it.m_id]; @@ -53,7 +54,7 @@ bool Inventory_Send(entity this, entity to, int sf) void Inventory_new(entity e) { Inventory inv = new(Inventory), bak = new(Inventory); - inv.classname = "inventory", bak.classname = "inventory"; + make_pure(inv); make_pure(bak); inv.inventory = bak; inv.drawonlytoclient = e; Net_LinkEntity((inv.owner = e).inventory = inv, false, 0, Inventory_Send); diff --git a/qcsrc/common/minigames/cl_minigames.qh b/qcsrc/common/minigames/cl_minigames.qh index 016e8a3ed..223e2c0b9 100644 --- a/qcsrc/common/minigames/cl_minigames.qh +++ b/qcsrc/common/minigames/cl_minigames.qh @@ -117,12 +117,12 @@ void HUD_MinigameMenu_CustomEntry(entity parent, string message, string event_ar REGISTRY(Minigames, BIT(3)) REGISTER_REGISTRY(RegisterMinigames) #define REGISTER_MINIGAME(name,nicename) \ - REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \ + REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \ void name##_hud_board(vector, vector); \ void name##_hud_status(vector, vector); \ int name##_client_event(entity, string, ...); \ REGISTER_INIT_POST(MINIGAME, name) { \ - this.classname = "minigame_descriptor"; \ + make_pure(this); \ this.netname = strzone(strtolower(#name)); \ this.message = nicename; \ this.minigame_hud_board = name##_hud_board; \ diff --git a/qcsrc/common/minigames/minigame/nmm.qc b/qcsrc/common/minigames/minigame/nmm.qc index 1e4da0507..93c88f657 100644 --- a/qcsrc/common/minigames/minigame/nmm.qc +++ b/qcsrc/common/minigames/minigame/nmm.qc @@ -79,9 +79,8 @@ string nmm_tile_build_vmill(entity tile) void nmm_spawn_tile(string id, entity minig, int distance) { // TODO global variable + list_next for simpler tile loops - entity e = spawn(); + entity e = new(minigame_nmm_tile); e.origin = minigame_tile_pos(id,7,7); - e.classname = "minigame_nmm_tile"; e.netname = id; e.owner = minig; e.team = 0; diff --git a/qcsrc/common/minigames/minigame/ttt.qc b/qcsrc/common/minigames/minigame/ttt.qc index 8c5005ed2..c3c76376c 100644 --- a/qcsrc/common/minigames/minigame/ttt.qc +++ b/qcsrc/common/minigames/minigame/ttt.qc @@ -642,8 +642,7 @@ int ttt_client_event(entity minigame, string event, ...) if ( spawnai ) { - entity aiplayer = spawn(); - aiplayer.classname = "minigame_player"; + entity aiplayer = new(minigame_player); aiplayer.owner = minigame; aiplayer.team = ai; aiplayer.minigame_playerslot = 0; diff --git a/qcsrc/common/minigames/sv_minigames.qc b/qcsrc/common/minigames/sv_minigames.qc index 56d0ece1a..403a79d40 100644 --- a/qcsrc/common/minigames/sv_minigames.qc +++ b/qcsrc/common/minigames/sv_minigames.qc @@ -131,12 +131,11 @@ int minigame_addplayer(entity minigame_session, entity player) return 0; minigame_rmplayer(player.active_minigame,player); } - entity player_pointer = spawn(); + entity player_pointer = new(minigame_player); int mgteam = minigame_session.minigame_event(minigame_session,"join",player,player_pointer); if ( mgteam ) { - player_pointer.classname = "minigame_player"; player_pointer.owner = minigame_session; player_pointer.minigame_players = player; player_pointer.team = mgteam; @@ -171,8 +170,7 @@ entity start_minigame(entity player, string minigame ) entity e = minigame_get_descriptor(minigame); if ( e ) { - entity minig = spawn(); - minig.classname = "minigame"; + entity minig = new(minigame); minig.netname = strzone(strcat(e.netname,"_",ftos(num_for_edict(minig)))); minig.descriptor = e; minig.minigame_event = e.minigame_event; diff --git a/qcsrc/common/minigames/sv_minigames.qh b/qcsrc/common/minigames/sv_minigames.qh index e36d690d9..b3a6ce2ee 100644 --- a/qcsrc/common/minigames/sv_minigames.qh +++ b/qcsrc/common/minigames/sv_minigames.qh @@ -49,10 +49,10 @@ bool minigame_SendEntity(entity this, entity to, int sf); REGISTRY(Minigames, BIT(3)) REGISTER_REGISTRY(RegisterMinigames) #define REGISTER_MINIGAME(name,nicename) \ - REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \ + REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \ int name##_server_event(entity, string, ...); \ REGISTER_INIT_POST(MINIGAME, name) { \ - this.classname = "minigame_descriptor"; \ + make_pure(this); \ this.netname = strzone(strtolower(#name)); \ this.message = nicename; \ this.minigame_event = name##_server_event; \ diff --git a/qcsrc/common/monsters/monster/shambler.qc b/qcsrc/common/monsters/monster/shambler.qc index 1a1fb450c..58ae391be 100644 --- a/qcsrc/common/monsters/monster/shambler.qc +++ b/qcsrc/common/monsters/monster/shambler.qc @@ -149,9 +149,8 @@ void M_Shambler_Attack_Lightning() monster_makevectors(self.enemy); - gren = spawn (); + gren = new(grenade); gren.owner = gren.realowner = self; - gren.classname = "grenade"; gren.bot_dodge = true; gren.bot_dodgerating = (autocvar_g_monster_shambler_attack_lightning_damage); gren.movetype = MOVETYPE_BOUNCE; diff --git a/qcsrc/common/monsters/monster/spider.qc b/qcsrc/common/monsters/monster/spider.qc index 8f42ca7fa..953ede71f 100644 --- a/qcsrc/common/monsters/monster/spider.qc +++ b/qcsrc/common/monsters/monster/spider.qc @@ -121,8 +121,7 @@ void M_Spider_Attack_Web() sound(self, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM); - entity proj = spawn (); - proj.classname = "plasma"; + entity proj = new(plasma); proj.owner = proj.realowner = self; proj.use = M_Spider_Attack_Web_Explode; proj.think = adaptor_think2use_hittype_splash; diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index f8294e3f5..7dbc9e326 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -36,7 +36,7 @@ void monster_dropitem() return; vector org = self.origin + ((self.mins + self.maxs) * 0.5); - entity e = spawn(); + entity e = new(droppedweapon); // use weapon handling to remove it on touch e.spawnfunc_checked = true; e.monster_loot = self.monster_loot; @@ -55,7 +55,6 @@ void monster_dropitem() setorigin(e, org); e.velocity = randomvec() * 175 + '0 0 325'; e.item_spawnshieldtime = time + 0.7; - e.classname = "droppedweapon"; // use weapon handling to remove it on touch SUB_SetFade(e, time + autocvar_g_monsters_drop_time, 1); setself(this); } diff --git a/qcsrc/common/mutators/mutator/waypoints/all.qh b/qcsrc/common/mutators/mutator/waypoints/all.qh index f7fd03837..6bc672902 100644 --- a/qcsrc/common/mutators/mutator/waypoints/all.qh +++ b/qcsrc/common/mutators/mutator/waypoints/all.qh @@ -28,7 +28,7 @@ ENDCLASS(Waypoint) REGISTRY(RadarIcons, BITS(7)) REGISTER_REGISTRY(RegisterRadarIcons) .int m_radaricon; -#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; } +#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { make_pure(this); this.m_radaricon = num; this.netname = #id; } REGISTER_WAYPOINT(Null, "", '0 0 0', 1); diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc index f0b768c57..1f4697d43 100644 --- a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc @@ -993,6 +993,7 @@ entity WaypointSprite_Spawn( ) { entity wp = new(sprite_waypoint); + make_pure(wp); wp.teleport_time = time + _lifetime; wp.fade_time = _lifetime; wp.exteriormodeltoclient = ref; diff --git a/qcsrc/common/nades/all.qc b/qcsrc/common/nades/all.qc index 30ad1782f..d56f2805f 100644 --- a/qcsrc/common/nades/all.qc +++ b/qcsrc/common/nades/all.qc @@ -52,7 +52,7 @@ void healer_setup(entity e) REGISTER_NET_LINKED(Nade_Heal, bool isNew) #ifdef CSQC { - Net_Accept(); + Net_Accept(Nade_Heal); int sf = ReadByte(); if (sf & 1) { this.origin_x = ReadCoord(); diff --git a/qcsrc/common/net_notice.qc b/qcsrc/common/net_notice.qc index f748f9903..317eec109 100644 --- a/qcsrc/common/net_notice.qc +++ b/qcsrc/common/net_notice.qc @@ -49,11 +49,9 @@ void sv_notice_toall(string _notice, float _howlong, float _modal) #ifdef CSQC void cl_notice_read() { - entity _notice; //float _done; //float _modal; - _notice = spawn(); - _notice.classname = "sv_notice"; + entity _notice = new(sv_notice); _notice.netname = strzone(ReadString()); _notice.alpha = ReadLong() + time; _notice.skin = ReadByte(); diff --git a/qcsrc/common/notifications.qc b/qcsrc/common/notifications.qc index 5a55c5552..c46988ddd 100644 --- a/qcsrc/common/notifications.qc +++ b/qcsrc/common/notifications.qc @@ -524,6 +524,7 @@ void Create_Notification_Entity( // Global Entity Setup // ===================== entity notif = spawn(); + make_pure(notif); switch(typeId) { case MSG_ANNCE: @@ -1842,8 +1843,8 @@ void Kill_Notification( if(killed_cpid != NO_CPID) { - net_notif = spawn(); - net_notif.classname = "net_kill_notification"; + net_notif = new(net_kill_notification); + make_pure(net_notif); net_notif.nent_broadcast = broadcast; net_notif.nent_client = client; net_notif.nent_net_type = MSG_CENTER_CPID; @@ -2093,9 +2094,9 @@ void Send_Notification( } else { - entity net_notif = spawn(); + entity net_notif = new(net_notification); + make_pure(net_notif); net_notif.owner = notif; - net_notif.classname = "net_notification"; net_notif.nent_broadcast = broadcast; net_notif.nent_client = client; net_notif.nent_net_type = net_type; diff --git a/qcsrc/common/triggers/func/bobbing.qc b/qcsrc/common/triggers/func/bobbing.qc index 8c7000d93..909f5cd97 100644 --- a/qcsrc/common/triggers/func/bobbing.qc +++ b/qcsrc/common/triggers/func/bobbing.qc @@ -69,8 +69,7 @@ spawnfunc(func_bobbing) return; // wait for targets to spawn - controller = spawn(); - controller.classname = "func_bobbing_controller"; + controller = new(func_bobbing_controller); controller.owner = self; controller.nextthink = time + 1; controller.think = func_bobbing_controller_think; diff --git a/qcsrc/common/triggers/func/door.qc b/qcsrc/common/triggers/func/door.qc index 74b0e549f..e2d122816 100644 --- a/qcsrc/common/triggers/func/door.qc +++ b/qcsrc/common/triggers/func/door.qc @@ -458,8 +458,7 @@ void door_spawnfield(vector fmins, vector fmaxs) entity trigger; vector t1 = fmins, t2 = fmaxs; - trigger = spawn(); - trigger.classname = "doortriggerfield"; + trigger = new(doortriggerfield); trigger.movetype = MOVETYPE_NONE; trigger.solid = SOLID_TRIGGER; trigger.owner = self; diff --git a/qcsrc/common/triggers/func/fourier.qc b/qcsrc/common/triggers/func/fourier.qc index 2b3d07f6e..31e383591 100644 --- a/qcsrc/common/triggers/func/fourier.qc +++ b/qcsrc/common/triggers/func/fourier.qc @@ -73,8 +73,7 @@ spawnfunc(func_fourier) self.active = ACTIVE_ACTIVE; // wait for targets to spawn - controller = spawn(); - controller.classname = "func_fourier_controller"; + controller = new(func_fourier_controller); controller.owner = self; controller.nextthink = time + 1; controller.think = func_fourier_controller_think; diff --git a/qcsrc/common/triggers/func/pendulum.qc b/qcsrc/common/triggers/func/pendulum.qc index d8bab869e..2d8aea35c 100644 --- a/qcsrc/common/triggers/func/pendulum.qc +++ b/qcsrc/common/triggers/func/pendulum.qc @@ -62,8 +62,7 @@ spawnfunc(func_pendulum) self.cnt = self.angles_z; // wait for targets to spawn - controller = spawn(); - controller.classname = "func_pendulum_controller"; + controller = new(func_pendulum_controller); controller.owner = self; controller.nextthink = time + 1; controller.think = func_pendulum_controller_think; diff --git a/qcsrc/common/triggers/func/vectormamamam.qc b/qcsrc/common/triggers/func/vectormamamam.qc index 57d3a0636..5c2086477 100644 --- a/qcsrc/common/triggers/func/vectormamamam.qc +++ b/qcsrc/common/triggers/func/vectormamamam.qc @@ -91,8 +91,7 @@ void func_vectormamamam_findtarget() self.destvec = self.origin - func_vectormamamam_origin(self, 0); entity controller; - controller = spawn(); - controller.classname = "func_vectormamamam_controller"; + controller = new(func_vectormamamam_controller); controller.owner = self; controller.nextthink = time + 1; controller.think = func_vectormamamam_controller_think; diff --git a/qcsrc/common/triggers/subs.qc b/qcsrc/common/triggers/subs.qc index d9de97301..850158a63 100644 --- a/qcsrc/common/triggers/subs.qc +++ b/qcsrc/common/triggers/subs.qc @@ -222,8 +222,7 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeedtype, float return; } - controller = spawn(); - controller.classname = "SUB_CalcMove_controller"; + controller = new(SUB_CalcMove_controller); controller.owner = self; controller.platmovetype = self.platmovetype; controller.platmovetype_start = self.platmovetype_start; diff --git a/qcsrc/common/triggers/trigger/jumppads.qc b/qcsrc/common/triggers/trigger/jumppads.qc index 8640fdf98..67659034a 100644 --- a/qcsrc/common/triggers/trigger/jumppads.qc +++ b/qcsrc/common/triggers/trigger/jumppads.qc @@ -407,7 +407,7 @@ void target_push_link() spawnfunc(target_push) { target_push_link(); } spawnfunc(info_notnull) { target_push_link(); } -spawnfunc(target_position) { target_push_link(); } +spawnfunc(target_position) { make_pure(this); target_push_link(); } #endif diff --git a/qcsrc/common/triggers/triggers.qc b/qcsrc/common/triggers/triggers.qc index b97d2b1d9..41180dd2c 100644 --- a/qcsrc/common/triggers/triggers.qc +++ b/qcsrc/common/triggers/triggers.qc @@ -148,8 +148,7 @@ void SUB_UseTargets() if (self.delay) { // create a temp object to fire at a later time - t = spawn(); - t.classname = "DelayedUse"; + t = new(DelayedUse); t.nextthink = time + self.delay; t.think = DelayThink; t.enemy = activator; diff --git a/qcsrc/common/turrets/cl_turrets.qc b/qcsrc/common/turrets/cl_turrets.qc index 582113cf8..6b0dbeeea 100644 --- a/qcsrc/common/turrets/cl_turrets.qc +++ b/qcsrc/common/turrets/cl_turrets.qc @@ -287,7 +287,7 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo if(trace_startsolid) return world; - gib = spawn(); + gib = new(turret_gib); setorigin(gib, _from); _setmodel(gib, _model); gib.colormod = _cmod; @@ -311,7 +311,6 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo gib.move_avelocity = prandomvec() * 32; gib.move_time = time; gib.damageforcescale = 1; - gib.classname = "turret_gib"; return gib; } diff --git a/qcsrc/common/turrets/sv_turrets.qc b/qcsrc/common/turrets/sv_turrets.qc index 49bd505ed..33e41cd49 100644 --- a/qcsrc/common/turrets/sv_turrets.qc +++ b/qcsrc/common/turrets/sv_turrets.qc @@ -1267,8 +1267,7 @@ float turret_initialize(Turret tur) entity e = find(world, classname, "turret_manager"); if(!e) { - e = spawn(); - e.classname = "turret_manager"; + e = new(turret_manager); e.think = turrets_manager_think; e.nextthink = time + 2; } @@ -1353,13 +1352,13 @@ float turret_initialize(Turret tur) self.nextthink = time + 1; self.nextthink += turret_count * sys_frametime; - self.tur_head = spawn(); + self.tur_head = new(turret_head); _setmodel(self.tur_head, tur.head_model); setsize(self.tur_head, '0 0 0', '0 0 0'); setorigin(self.tur_head, '0 0 0'); setattachment(self.tur_head, self, "tag_head"); - self.tur_head.netname = self.tur_head.classname = "turret_head"; + self.tur_head.netname = self.tur_head.classname; self.tur_head.team = self.team; self.tur_head.owner = self; self.tur_head.takedamage = DAMAGE_NO; diff --git a/qcsrc/common/turrets/turret/walker.qc b/qcsrc/common/turrets/turret/walker.qc index 43ac006ae..eac40d220 100644 --- a/qcsrc/common/turrets/turret/walker.qc +++ b/qcsrc/common/turrets/turret/walker.qc @@ -233,13 +233,12 @@ void walker_fire_rocket(vector org) te_explosion (org); - rocket = spawn (); + rocket = new(walker_rocket); setorigin(rocket, org); sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM); setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - rocket.classname = "walker_rocket"; rocket.owner = self; rocket.bot_dodge = true; rocket.bot_dodgerating = 50; diff --git a/qcsrc/common/turrets/util.qc b/qcsrc/common/turrets/util.qc index 53c5fb74d..b0667c89a 100644 --- a/qcsrc/common/turrets/util.qc +++ b/qcsrc/common/turrets/util.qc @@ -224,10 +224,7 @@ void marker_think() void mark_error(vector where,float lifetime) { - entity err; - - err = spawn(); - err.classname = "error_marker"; + entity err = new(error_marker); setmodel(err, MDL_MARKER); setorigin(err,where); err.movetype = MOVETYPE_NONE; @@ -240,10 +237,7 @@ void mark_error(vector where,float lifetime) void mark_info(vector where,float lifetime) { - entity err; - - err = spawn(); - err.classname = "info_marker"; + entity err = spawn(info_marker); setmodel(err, MDL_MARKER); setorigin(err,where); err.movetype = MOVETYPE_NONE; @@ -256,10 +250,7 @@ void mark_info(vector where,float lifetime) entity mark_misc(vector where,float lifetime) { - entity err; - - err = spawn(); - err.classname = "mark_misc"; + entity err = spawn(mark_misc); setmodel(err, MDL_MARKER); setorigin(err,where); err.movetype = MOVETYPE_NONE; diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 7ac910f99..a6a57c7df 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -803,8 +803,8 @@ float cvar_settemp(string tmp_cvar, string tmp_value) if(created_saved_value != -1) { // creating a new entity to keep track of this cvar - e = spawn(); - e.classname = "saved_cvar_value"; + e = new(saved_cvar_value); + make_pure(e); e.netname = strzone(tmp_cvar); e.message = strzone(cvar_string(tmp_cvar)); created_saved_value = 1; diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index a00cdcfa3..e1a5f1f72 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -455,10 +455,8 @@ void vehicles_reset_colors() void vehicles_clearreturn(entity veh) { - entity ret; // Remove "return helper", if any. - ret = findchain(classname, "vehicle_return"); - while(ret) + for (entity ret = findchain(classname, "vehicle_return"); ret; ret = ret.chain) { if(ret.wp00 == veh) { @@ -471,7 +469,6 @@ void vehicles_clearreturn(entity veh) return; } - ret = ret.chain; } } @@ -548,8 +545,7 @@ void vehicles_setreturn(entity veh) vehicles_clearreturn(veh); - ret = spawn(); - ret.classname = "vehicle_return"; + ret = new(vehicle_return); ret.wp00 = veh; ret.team = veh.team; ret.think = vehicles_showwp; @@ -1234,9 +1230,9 @@ bool vehicle_initialize(entity veh, bool nodrop) self.vehicle_flags |= VHF_ISVEHICLE; - self.vehicle_viewport = spawn(); - self.vehicle_hudmodel = spawn(); - self.tur_head = spawn(); + self.vehicle_viewport = new(vehicle_viewport); + self.vehicle_hudmodel = new(vehicle_hudmodel); + self.tur_head = new(tur_head); self.tur_head.owner = self; self.takedamage = DAMAGE_NO; self.bot_attack = true; diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qc b/qcsrc/common/vehicles/vehicle/bumblebee.qc index 6e9099a17..244b4e2f6 100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qc @@ -859,9 +859,9 @@ spawnfunc(vehicle_bumblebee) self.vehicle_shieldent.alpha = -1; self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW; - self.gun1 = spawn(); - self.gun2 = spawn(); - self.gun3 = spawn(); + self.gun1 = new(vehicle_playerslot); + self.gun2 = new(vehicle_playerslot); + self.gun3 = new(bumblebee_raygun); self.vehicle_flags |= VHF_MULTISLOT; @@ -869,8 +869,6 @@ spawnfunc(vehicle_bumblebee) self.gun2.owner = self; self.gun3.owner = self; - self.gun1.classname = self.gun2.classname = "vehicle_playerslot"; - setmodel(self.gun1, MDL_VEH_BUMBLEBEE_CANNON_RIGHT); setmodel(self.gun2, MDL_VEH_BUMBLEBEE_CANNON_LEFT); setmodel(self.gun3, MDL_VEH_BUMBLEBEE_CANNON_CENTER); diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc index 7d90dd485..c81f5d9ba 100644 --- a/qcsrc/common/vehicles/vehicle/raptor.qc +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@ -671,10 +671,10 @@ spawnfunc(vehicle_raptor) self.frame = 0; - self.bomb1 = spawn(); - self.bomb2 = spawn(); - self.gun1 = spawn(); - self.gun2 = spawn(); + self.bomb1 = new(raptor_bomb); + self.bomb2 = new(raptor_bomb); + self.gun1 = new(raptor_gun); + self.gun2 = new(raptor_gun); setmodel(self.bomb1, MDL_VEH_RAPTOR_CB_FOLDED); setmodel(self.bomb2, MDL_VEH_RAPTOR_CB_FOLDED); @@ -705,7 +705,7 @@ spawnfunc(vehicle_raptor) self.angles = self.bomb1.angles; self.bomb1.angles = '0 0 0'; - spinner = spawn(); + spinner = new(raptor_spinner); spinner.owner = self; setmodel(spinner, MDL_VEH_RAPTOR_PROP); setattachment(spinner, self, "engine_left"); @@ -713,7 +713,7 @@ spawnfunc(vehicle_raptor) spinner.avelocity = '0 90 0'; self.bomb1.gun1 = spinner; - spinner = spawn(); + spinner = new(raptor_spinner); spinner.owner = self; setmodel(spinner, MDL_VEH_RAPTOR_PROP); setattachment(spinner, self, "engine_right"); diff --git a/qcsrc/common/weapons/weapon/arc.qc b/qcsrc/common/weapons/weapon/arc.qc index 965827f3d..c2440e61a 100644 --- a/qcsrc/common/weapons/weapon/arc.qc +++ b/qcsrc/common/weapons/weapon/arc.qc @@ -584,8 +584,7 @@ void W_Arc_Beam(float burst) if(time - self.beam_prev > 1) sound(self, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM); - entity beam = self.arc_beam = spawn(); - beam.classname = "W_Arc_Beam"; + entity beam = self.arc_beam = new(W_Arc_Beam); beam.solid = SOLID_NOT; beam.think = W_Arc_Beam_Think; beam.owner = self; diff --git a/qcsrc/common/weapons/weapon/blaster.qc b/qcsrc/common/weapons/weapon/blaster.qc index 2aa8bbdd6..3503a916b 100644 --- a/qcsrc/common/weapons/weapon/blaster.qc +++ b/qcsrc/common/weapons/weapon/blaster.qc @@ -101,9 +101,8 @@ void W_Blaster_Attack( W_SetupShot_Dir(actor, s_forward, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, atk_damage); Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - entity missile = spawn(); + entity missile = new(blasterbolt); missile.owner = missile.realowner = actor; - missile.classname = "blasterbolt"; missile.bot_dodge = true; missile.bot_dodgerating = atk_damage; PROJECTILE_MAKETRIGGER(missile); diff --git a/qcsrc/common/weapons/weapon/crylink.qc b/qcsrc/common/weapons/weapon/crylink.qc index 083d7e0d0..c8c13898e 100644 --- a/qcsrc/common/weapons/weapon/crylink.qc +++ b/qcsrc/common/weapons/weapon/crylink.qc @@ -366,10 +366,9 @@ void W_Crylink_Attack(Weapon thiswep) proj = prevproj = firstproj = world; for(counter = 0; counter < shots; ++counter) { - proj = spawn(); + proj = new(spike); proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; - proj.classname = "spike"; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage); if(shots == 1) { @@ -475,10 +474,9 @@ void W_Crylink_Attack2(Weapon thiswep) proj = prevproj = firstproj = world; for(counter = 0; counter < shots; ++counter) { - proj = spawn(); + proj = new(spike); proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; - proj.classname = "spike"; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage); if(shots == 1) { @@ -614,9 +612,8 @@ void W_Crylink_Attack2(Weapon thiswep) pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed)); - linkjoineffect = spawn(); + linkjoineffect = new(linkjoineffect); linkjoineffect.think = W_Crylink_LinkJoinEffect_Think; - linkjoineffect.classname = "linkjoineffect"; linkjoineffect.nextthink = time + w_crylink_linkjoin_time; linkjoineffect.owner = actor; setorigin(linkjoineffect, pos); diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index 63acee37a..b0df034e2 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -264,8 +264,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep) Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - proj = spawn(); - proj.classname = "electro_bolt"; + proj = new(electro_bolt); proj.owner = proj.realowner = self; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_PRI(electro, damage); @@ -364,8 +363,7 @@ void W_Electro_Attack_Orb(Weapon thiswep) Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - entity proj = spawn(); - proj.classname = "electro_orb"; + entity proj = new(electro_orb); proj.owner = proj.realowner = self; proj.use = W_Electro_Explode; proj.think = adaptor_think2use_hittype_splash; diff --git a/qcsrc/common/weapons/weapon/fireball.qc b/qcsrc/common/weapons/weapon/fireball.qc index 477aef833..43f414240 100644 --- a/qcsrc/common/weapons/weapon/fireball.qc +++ b/qcsrc/common/weapons/weapon/fireball.qc @@ -188,8 +188,7 @@ void W_Fireball_Attack1(void) Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - proj = spawn(); - proj.classname = "plasma_prim"; + proj = new(plasma_prim); proj.owner = proj.realowner = self; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage); @@ -324,9 +323,8 @@ void W_Fireball_Attack2(void) Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - proj = spawn(); + proj = new(grenade); proj.owner = proj.realowner = self; - proj.classname = "grenade"; proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage); proj.movetype = MOVETYPE_BOUNCE; diff --git a/qcsrc/common/weapons/weapon/hagar.qc b/qcsrc/common/weapons/weapon/hagar.qc index c9d1c520c..203f5667c 100644 --- a/qcsrc/common/weapons/weapon/hagar.qc +++ b/qcsrc/common/weapons/weapon/hagar.qc @@ -133,9 +133,8 @@ void W_Hagar_Attack(Weapon thiswep) Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - missile = spawn(); + missile = new(missile); missile.owner = missile.realowner = self; - missile.classname = "missile"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR_PRI(hagar, damage); @@ -176,9 +175,8 @@ void W_Hagar_Attack2(Weapon thiswep) Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - missile = spawn(); + missile = new(missile); missile.owner = missile.realowner = self; - missile.classname = "missile"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage); @@ -236,9 +234,8 @@ void W_Hagar_Attack2_Load_Release(int slot) missile = world; for(counter = 0; counter < shots; ++counter) { - missile = spawn(); + missile = new(missile); missile.owner = missile.realowner = self; - missile.classname = "missile"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage); diff --git a/qcsrc/common/weapons/weapon/hlac.qc b/qcsrc/common/weapons/weapon/hlac.qc index 639847a7e..e1ec82b00 100644 --- a/qcsrc/common/weapons/weapon/hlac.qc +++ b/qcsrc/common/weapons/weapon/hlac.qc @@ -87,9 +87,8 @@ void W_HLAC_Attack(Weapon thiswep) self.punchangle_y = random() - 0.5; } - missile = spawn(); + missile = new(hlacbolt); missile.owner = missile.realowner = self; - missile.classname = "hlacbolt"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage); @@ -130,9 +129,8 @@ void W_HLAC_Attack2(void) W_SetupShot(self, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage)); Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - missile = spawn(); + missile = new(hlacbolt); missile.owner = missile.realowner = self; - missile.classname = "hlacbolt"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage); diff --git a/qcsrc/common/weapons/weapon/minelayer.qc b/qcsrc/common/weapons/weapon/minelayer.qc index fa12ace6a..b5a811b1d 100644 --- a/qcsrc/common/weapons/weapon/minelayer.qc +++ b/qcsrc/common/weapons/weapon/minelayer.qc @@ -67,8 +67,7 @@ void W_MineLayer_Stick(entity to) // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile - entity newmine; - newmine = spawn(); + entity newmine = spawn(); newmine.classname = self.classname; newmine.bot_dodge = self.bot_dodge; diff --git a/qcsrc/common/weapons/weapon/mortar.qc b/qcsrc/common/weapons/weapon/mortar.qc index e1a295936..2a29f6bb3 100644 --- a/qcsrc/common/weapons/weapon/mortar.qc +++ b/qcsrc/common/weapons/weapon/mortar.qc @@ -209,9 +209,8 @@ void W_Mortar_Attack(Weapon thiswep) Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - gren = spawn(); + gren = new(grenade); gren.owner = gren.realowner = self; - gren.classname = "grenade"; gren.bot_dodge = true; gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage); gren.movetype = MOVETYPE_BOUNCE; @@ -258,9 +257,8 @@ void W_Mortar_Attack2(Weapon thiswep) Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - gren = spawn(); + gren = new(grenade); gren.owner = gren.realowner = self; - gren.classname = "grenade"; gren.bot_dodge = true; gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage); gren.movetype = MOVETYPE_BOUNCE; diff --git a/qcsrc/common/weapons/weapon/porto.qc b/qcsrc/common/weapons/weapon/porto.qc index 89019c40c..35689dadd 100644 --- a/qcsrc/common/weapons/weapon/porto.qc +++ b/qcsrc/common/weapons/weapon/porto.qc @@ -251,11 +251,10 @@ void W_Porto_Attack(float type) //Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - gren = spawn(); + gren = new(porto); gren.cnt = type; gren.owner = gren.realowner = self; gren.playerid = self.playerid; - gren.classname = "porto"; gren.bot_dodge = true; gren.bot_dodgerating = 200; gren.movetype = MOVETYPE_BOUNCEMISSILE; diff --git a/qcsrc/common/weapons/weapon/seeker.qc b/qcsrc/common/weapons/weapon/seeker.qc index 9bac67321..cb55f4630 100644 --- a/qcsrc/common/weapons/weapon/seeker.qc +++ b/qcsrc/common/weapons/weapon/seeker.qc @@ -258,9 +258,8 @@ void W_Seeker_Fire_Missile(Weapon thiswep, vector f_diff, entity m_target) //self.detornator = false; - missile = spawn(); + missile = new(seeker_missile); missile.owner = missile.realowner = self; - missile.classname = "seeker_missile"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR(seeker, missile_damage); @@ -348,9 +347,8 @@ void W_Seeker_Fire_Flac(Weapon thiswep) Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - missile = spawn(); + missile = new(missile); missile.owner = missile.realowner = self; - missile.classname = "missile"; missile.bot_dodge = true; missile.bot_dodgerating = WEP_CVAR(seeker, flac_damage); missile.touch = W_Seeker_Flac_Explode; @@ -524,9 +522,8 @@ void W_Seeker_Tag_Touch(void) else { //sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n")); - e = spawn(); + e = new(tag_tracker); e.cnt = WEP_CVAR(seeker, missile_count); - e.classname = "tag_tracker"; e.owner = self.owner; e.realowner = self.realowner; @@ -563,9 +560,8 @@ void W_Seeker_Fire_Tag(Weapon thiswep) W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, SND(TAG_FIRE), CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count)); - missile = spawn(); + missile = new(seeker_tag); missile.owner = missile.realowner = self; - missile.classname = "seeker_tag"; missile.bot_dodge = true; missile.bot_dodgerating = 50; missile.touch = W_Seeker_Tag_Touch; diff --git a/qcsrc/common/weapons/weapon/shockwave.qc b/qcsrc/common/weapons/weapon/shockwave.qc index 97061567c..df2c25d2a 100644 --- a/qcsrc/common/weapons/weapon/shockwave.qc +++ b/qcsrc/common/weapons/weapon/shockwave.qc @@ -234,8 +234,8 @@ void W_Shockwave_Melee(Weapon thiswep, entity actor, int slot, int fire) sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTN_NORM); weapon_thinkf(actor, slot, WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready); - entity meleetemp; - meleetemp = spawn(); + entity meleetemp = new(meleetemp); + make_pure(meleetemp); meleetemp.owner = meleetemp.realowner = actor; meleetemp.think = W_Shockwave_Melee_Think; meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor(); diff --git a/qcsrc/common/weapons/weapon/shotgun.qc b/qcsrc/common/weapons/weapon/shotgun.qc index e3f85daa1..b3eef1627 100644 --- a/qcsrc/common/weapons/weapon/shotgun.qc +++ b/qcsrc/common/weapons/weapon/shotgun.qc @@ -186,8 +186,8 @@ void W_Shotgun_Attack2(Weapon thiswep, entity actor, int slot, int fire) sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM); weapon_thinkf(actor, slot, WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready); - entity meleetemp; - meleetemp = spawn(); + entity meleetemp = new(meleetemp); + make_pure(meleetemp); meleetemp.realowner = actor; meleetemp.think = W_Shotgun_Melee_Think; meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor(); diff --git a/qcsrc/common/weapons/weapon/vaporizer.qc b/qcsrc/common/weapons/weapon/vaporizer.qc index d4208501b..46dc5ee80 100644 --- a/qcsrc/common/weapons/weapon/vaporizer.qc +++ b/qcsrc/common/weapons/weapon/vaporizer.qc @@ -150,8 +150,7 @@ void W_RocketMinsta_Attack2(void) while(counter < total) { - proj = spawn (); - proj.classname = "plasma_prim"; + proj = new(plasma_prim); proj.owner = proj.realowner = self; proj.bot_dodge = true; proj.bot_dodgerating = autocvar_g_rm_laser_damage; @@ -203,8 +202,7 @@ void W_RocketMinsta_Attack3 (void) while(counter < total) { - proj = spawn (); - proj.classname = "plasma_prim"; + proj = new(plasma_prim); proj.owner = proj.realowner = self; proj.bot_dodge = true; proj.bot_dodgerating = autocvar_g_rm_laser_damage; diff --git a/qcsrc/lib/defer.qh b/qcsrc/lib/defer.qh index eb56dce08..749e4a665 100644 --- a/qcsrc/lib/defer.qh +++ b/qcsrc/lib/defer.qh @@ -38,10 +38,10 @@ Remove self void defer(float fdelay, void() func) { SELFPARAM(); - entity e; - e = spawn(); - e.owner = self; + entity e = new(deferred); + make_pure(e); + e.owner = this; e.use = func; e.think = defer_think; e.nextthink = time + fdelay; diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh index c3043806a..615aa5162 100644 --- a/qcsrc/lib/net.qh +++ b/qcsrc/lib/net.qh @@ -60,10 +60,10 @@ .void(entity this, bool isNew)m_read; #ifdef CSQC - #define Net_Accept() \ + #define Net_Accept(classname) \ do \ { \ - if (!this) this = spawn(); \ + if (!this) this = new(classname); \ } \ while (0) #define Net_Reject() \ @@ -87,9 +87,12 @@ void Ent_Read##id(entity this, param) \ { \ this = self; \ + this.sourceLocFile = __FILE__; \ + this.sourceLocLine = __LINE__; \ } \ - REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) \ + REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \ { \ + make_pure(this); \ this.netname = #id; \ this.m_read = Ent_Read##id; \ } \ @@ -97,13 +100,14 @@ #else #define REGISTER_NET_LINKED(id, param) \ const bool NET_##id##_istemp = false; \ - REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) \ + REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \ { \ + make_pure(this); \ this.netname = #id; \ } #endif -REGISTRY(LinkedEntities, BIT(0)) +REGISTRY(LinkedEntities, BITS(2)) REGISTER_REGISTRY(RegisterLinkedEntities) REGISTRY_SORT(LinkedEntities, netname, 0) STATIC_INIT(RegisterLinkedEntities_renumber) @@ -115,8 +119,9 @@ STATIC_INIT(RegisterLinkedEntities_renumber) #ifdef CSQC #define REGISTER_NET_TEMP(id, param) \ void Net_Read##id(entity this, param); \ - REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) \ + REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \ { \ + make_pure(this); \ this.netname = #id; \ this.m_read = Net_Read##id; \ } \ @@ -124,13 +129,14 @@ STATIC_INIT(RegisterLinkedEntities_renumber) #else #define REGISTER_NET_TEMP(id, param) \ const bool NET_##id##_istemp = true; \ - REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) \ + REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \ { \ + make_pure(this); \ this.netname = #id; \ } #endif -REGISTRY(TempEntities, BIT(0)) +REGISTRY(TempEntities, BITS(2)) REGISTER_REGISTRY(RegisterTempEntities) REGISTRY_SORT(TempEntities, netname, 0) STATIC_INIT(RegisterTempEntities_renumber) @@ -164,6 +170,8 @@ STATIC_INIT(RegisterTempEntities_renumber) return v; } #else + const int MSG_ENTITY = 5; + void WriteInt24_t(float dst, float val) { float v; diff --git a/qcsrc/lib/oo.qh b/qcsrc/lib/oo.qh index 6a9a2e3b7..2925e9ee0 100644 --- a/qcsrc/lib/oo.qh +++ b/qcsrc/lib/oo.qh @@ -10,17 +10,28 @@ #define NULL (world) #endif +.vector origin; +.bool pure_data; +#define make_pure(e) \ + do \ + { \ + (e).pure_data = true; \ + } \ + while (0) +#define is_pure(e) ((e).pure_data) + .string classname; /** Location entity was spawned from in source */ .string sourceLocFile; .int sourceLocLine; entity _spawn(); -entity __spawn(string _classname, string _sourceFile, int _sourceLine) +entity __spawn(string _classname, string _sourceFile, int _sourceLine, bool pure) { entity this = _spawn(); this.classname = _classname; this.sourceLocFile = _sourceFile; this.sourceLocLine = _sourceLine; + if (pure) make_pure(this); return this; } @@ -30,13 +41,13 @@ entity __spawn(string _classname, string _sourceFile, int _sourceLine) #ifndef QCC_SUPPORT_ENTITYCLASS #define entityclass_2(name, base) typedef entity name #define class(name) - #define new(class) __spawn( #class, __FILE__, __LINE__) + #define new(class) __spawn( #class, __FILE__, __LINE__, false) #else #define entityclass_2(name, base) entityclass name : base {} #define class(name) [[class(name)]] - #define new(class) ((class) __spawn( #class, __FILE__, __LINE__)) + #define new(class) ((class) __spawn( #class, __FILE__, __LINE__, false)) #endif -#define spawn() new(entity) +#define spawn() __spawn("entity", __FILE__, __LINE__, false) // Classes have a `spawn##cname(entity)` constructor // The parameter is used across [[accumulate]] functions @@ -82,6 +93,7 @@ STATIC_INIT(RegisterClasses) void cname##_vtbl_init() \ { \ cname e = new(vtbl); \ + make_pure(e); \ spawn##cname##_static(e); \ e.vtblname = #cname; \ /* Top level objects refer to themselves */ \ @@ -164,7 +176,7 @@ CLASS(Object, ); } return s; } - METHOD(Object, display, void(entity this, void(string name, string icon)returns)) + METHOD(Object, display, void(entity this, void(string name, string icon) returns)) { returns(sprintf("entity %i", this), "nopreview_map"); } diff --git a/qcsrc/lib/sortlist.qc b/qcsrc/lib/sortlist.qc index dfb3d7f07..fecc79bdf 100644 --- a/qcsrc/lib/sortlist.qc +++ b/qcsrc/lib/sortlist.qc @@ -2,8 +2,8 @@ entity Sort_Spawn() { - entity sort; - sort = spawn(); + entity sort = new(sortlist); + make_pure(sort); sort.sort_next = NULL; sort.chain = sort; return sort; diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh index f4242ebc3..8a17854cb 100644 --- a/qcsrc/lib/spawnfunc.qh +++ b/qcsrc/lib/spawnfunc.qh @@ -33,6 +33,11 @@ noref bool require_spawnfunc_prefix; void spawnfunc_##id(entity this) \ { \ this = self; \ + if (!this.sourceLocFile) \ + { \ + this.sourceLocFile = __FILE__; \ + this.sourceLocLine = __LINE__; \ + } \ if (!this.spawnfunc_checked) \ { \ for (int i = 0, n = numentityfields(); i < n; ++i) \ @@ -68,6 +73,8 @@ noref bool require_spawnfunc_prefix; /**/ #define FIELDS_UNION(fld) \ + FIELD_SCALAR(fld, sourceLocFile) \ + FIELD_SCALAR(fld, sourceLocLine) \ FIELD_SCALAR(fld, Version) \ FIELD_SCALAR(fld, ammo_cells) \ FIELD_SCALAR(fld, ammo_nails) \ diff --git a/qcsrc/lib/urllib.qc b/qcsrc/lib/urllib.qc index c60201b58..0a48ef6cd 100644 --- a/qcsrc/lib/urllib.qc +++ b/qcsrc/lib/urllib.qc @@ -94,8 +94,8 @@ void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) // attempts to close will result in a reading handle // create a writing end that does nothing yet - e = spawn(); - e.classname = "url_single_fopen_file"; + e = new(url_single_fopen_file); + make_pure(e); e.url_url = strzone(url); e.url_fh = URL_FH_CURL; e.url_wbuf = buf_create(); @@ -143,8 +143,8 @@ void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) // Make a dummy handle object (no buffers at // all). Wait for data to come from the // server, then call the callback - e = spawn(); - e.classname = "url_single_fopen_file"; + e = new(url_single_fopen_file); + make_pure(e); e.url_url = strzone(url); e.url_fh = URL_FH_CURL; e.url_rbuf = -1; @@ -165,8 +165,8 @@ void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) { case FILE_WRITE: case FILE_APPEND: - e = spawn(); - e.classname = "url_single_fopen_stdout"; + e = new(url_single_fopen_stdout); + make_pure(e); e.url_fh = URL_FH_STDOUT; e.url_ready = rdy; e.url_ready_pass = pass; @@ -189,8 +189,8 @@ void url_single_fopen(string url, int mode, url_ready_func rdy, entity pass) } else { - e = spawn(); - e.classname = "url_single_fopen_file"; + e = new(url_single_fopen_file); + make_pure(e); e.url_fh = fh; e.url_ready = rdy; e.url_ready_pass = pass; @@ -364,9 +364,8 @@ void url_multi_fopen(string url, int mode, url_ready_func rdy, entity pass) return; } - entity me; - me = spawn(); - me.classname = "url_multi"; + entity me = new(url_multi); + make_pure(me); me.url_url = strzone(url); me.url_attempt = 0; me.url_mode = mode; diff --git a/qcsrc/lib/warpzone/client.qc b/qcsrc/lib/warpzone/client.qc index aba39c2cb..49216057c 100644 --- a/qcsrc/lib/warpzone/client.qc +++ b/qcsrc/lib/warpzone/client.qc @@ -30,8 +30,7 @@ void WarpZone_Read(float isnew) warpzone_warpzones_exist = 1; if (!self.enemy) { - self.enemy = spawn(); - self.enemy.classname = "warpzone_from"; + self.enemy = new(warpzone_from); } self.classname = "trigger_warpzone"; @@ -149,8 +148,8 @@ void WarpZone_Camera_Read(float isnew) void CL_RotateMoves(vector ang) = #638; void WarpZone_Teleported_Read(float isnew) {SELFPARAM(); - vector v; self.classname = "warpzone_teleported"; + vector v; v.x = ReadCoord(); v.y = ReadCoord(); v.z = ReadCoord(); diff --git a/qcsrc/lib/warpzone/common.qc b/qcsrc/lib/warpzone/common.qc index 6fe901bd8..a142b8209 100644 --- a/qcsrc/lib/warpzone/common.qc +++ b/qcsrc/lib/warpzone/common.qc @@ -186,8 +186,8 @@ void WarpZone_Trace_InitTransform() { if(!WarpZone_trace_transform) { - WarpZone_trace_transform = spawn(); - WarpZone_trace_transform.classname = "warpzone_trace_transform"; + WarpZone_trace_transform = new(warpzone_trace_transform); + make_pure(WarpZone_trace_transform); } WarpZone_Accumulator_Clear(WarpZone_trace_transform); } @@ -572,37 +572,20 @@ vector WarpZoneLib_NearestPointOnBox(vector mi, vector ma, vector org) bool WarpZoneLib_BadEntity(entity e) { - string myclassname = e.classname; - if (e.instanceOfObject) return true; - switch(myclassname) + string s = e.classname; + if (is_pure(e)) return true; + switch (s) { - case "deathtype": - case "weaponentity": - case "exteriorweaponentity": - case "csqc_score_team": - case "pingplreport": - case "ent_client_scoreinfo": - case "saved_cvar_value": - case "accuracy": case "entcs_sender": case "entcs_receiver": - case "clientinit": - case "sprite_waypoint": - case "waypoint": - case "gibsplash": - //case "net_linked": // actually some real entities are linked without classname, fail + // case "net_linked": // actually some real entities are linked without classname, fail case "": return true; } - if(startsWith(myclassname, "msg_")) - return true; - - if(startsWith(myclassname, "target_")) - return true; + if (startsWith(s, "target_")) return true; - if(startsWith(myclassname, "info_")) - return true; + if (startsWith(s, "info_")) return true; return false; } @@ -703,8 +686,7 @@ void WarpZone_RefSys_CheckCreate(entity me) { if(me.WarpZone_refsys.owner != me) { - me.WarpZone_refsys = spawn(); - me.WarpZone_refsys.classname = "warpzone_refsys"; + me.WarpZone_refsys = new(warpzone_refsys); me.WarpZone_refsys.owner = me; me.WarpZone_refsys.think = WarpZone_RefSys_GC; me.WarpZone_refsys.nextthink = time + 1; diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc index e21e4cab4..ec109dad9 100644 --- a/qcsrc/lib/warpzone/server.qc +++ b/qcsrc/lib/warpzone/server.qc @@ -137,7 +137,7 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1) // instead of fixangle, send the transform to the client for smoother operation player.fixangle = false; - entity ts = spawn(); + entity ts = new(warpzone_teleported); setmodel(ts, MDL_Null); ts.SendEntity = WarpZone_Teleported_Send; ts.SendFlags = 0xFFFFFF; @@ -147,7 +147,6 @@ float WarpZone_Teleport(entity wz, entity player, float f0, float f1) ts.owner = player; ts.enemy = wz; ts.effects = EF_NODEPTHTEST; - ts.classname = "warpzone_teleported"; ts.angles = wz.warpzone_transform; } #endif diff --git a/qcsrc/menu/xonotic/serverlist.qc b/qcsrc/menu/xonotic/serverlist.qc index 2cee6162f..3819036ad 100644 --- a/qcsrc/menu/xonotic/serverlist.qc +++ b/qcsrc/menu/xonotic/serverlist.qc @@ -173,9 +173,7 @@ void RegisterSLCategories() #define SLIST_CATEGORY(name,enoverride,dioverride,str) \ SET_FIELD_COUNT(name, CATEGORY_FIRST, category_ent_count) \ CHECK_MAX_COUNT(name, MAX_CATEGORIES, category_ent_count, "SLIST_CATEGORY") \ - cat = spawn(); \ - categories[name - 1] = cat; \ - cat.classname = "slist_category"; \ + cat = categories[name - 1] = new(slist_category); \ cat.cat_name = strzone(#name); \ cat.cat_enoverride_string = strzone(SLIST_CATEGORY_AUTOCVAR(name)); \ cat.cat_dioverride_string = strzone(dioverride); \ diff --git a/qcsrc/server/bot/aim.qc b/qcsrc/server/bot/aim.qc index 50e1d456f..954154029 100644 --- a/qcsrc/server/bot/aim.qc +++ b/qcsrc/server/bot/aim.qc @@ -19,7 +19,7 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f if (targ.solid < SOLID_BBOX) // SOLID_NOT and SOLID_TRIGGER return false; // could never hit it if (!tracetossent) - tracetossent = spawn(); + tracetossent = new(tracetossent); tracetossent.owner = ignore; setsize(tracetossent, m1, m2); savesolid = targ.solid; @@ -38,7 +38,7 @@ float findtrajectorywithleading(vector org, vector m1, vector m2, entity targ, f } if (!tracetossfaketarget) - tracetossfaketarget = spawn(); + tracetossfaketarget = new(tracetossfaketarget); tracetossfaketarget.solid = savesolid; tracetossfaketarget.movetype = targ.movetype; _setmodel(tracetossfaketarget, targ.model); // no low precision diff --git a/qcsrc/server/bot/scripting.qc b/qcsrc/server/bot/scripting.qc index 9dfc26de7..e62c99b5b 100644 --- a/qcsrc/server/bot/scripting.qc +++ b/qcsrc/server/bot/scripting.qc @@ -1118,9 +1118,8 @@ void bot_setcurrentcommand() if(!self.bot_cmd_current) { - self.bot_cmd_current = spawn(); - self.bot_cmd_current.classname = "bot_cmd"; - self.bot_cmd_current.is_bot_cmd = 1; + self.bot_cmd_current = new(bot_cmd); + self.bot_cmd_current.is_bot_cmd = true; } bot_cmd = self.bot_cmd_current; diff --git a/qcsrc/server/bot/waypoints.qc b/qcsrc/server/bot/waypoints.qc index 156ad79fc..fe767b8c9 100644 --- a/qcsrc/server/bot/waypoints.qc +++ b/qcsrc/server/bot/waypoints.qc @@ -27,9 +27,9 @@ entity waypoint_spawn(vector m1, vector m2, float f) w = find(w, classname, "waypoint"); } - w = spawn(); + w = new(waypoint); + make_pure(w); w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; - w.classname = "waypoint"; w.wpflags = f; setorigin(w, (m1 + m2) * 0.5); setsize(w, m1 - w.origin, m2 - w.origin); diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index 4b6405581..1313cb7f2 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -150,8 +150,7 @@ float CheatImpulse(float i) // shared with regular waypoint init, so this is not a cheat by itself if(!self.personal) { - self.personal = spawn(); - self.personal.classname = "personal_wp"; + self.personal = new(personal_wp); } self.personal.origin = self.origin; self.personal.v_angle = self.v_angle; @@ -402,8 +401,7 @@ float CheatCommand(float argc) break; case "dragbox_spawn": { IS_CHEAT(0, argc, 0); - entity e = spawn(); - e.classname = "dragbox_box"; + entity e = new(dragbox_box); e.think = DragBox_Think; e.nextthink = time; e.solid = -1; // black @@ -413,8 +411,7 @@ float CheatCommand(float argc) else e.cnt = max(0, drag_lastcnt); - e.aiment = spawn(); - e.aiment.classname = "dragbox_corner_1"; + e.aiment = new(dragbox_corner_1); e.aiment.owner = e; setmodel(e.aiment, MDL_MARKER); e.aiment.skin = 0; @@ -427,8 +424,7 @@ float CheatCommand(float argc) setorigin(e.aiment, trace_endpos); } - e.enemy = spawn(); - e.enemy.classname = "dragbox_corner_2"; + e.enemy = new(dragbox_corner_2); e.enemy.owner = e; setmodel(e.enemy, MDL_MARKER); e.enemy.skin = 1; @@ -442,13 +438,11 @@ float CheatCommand(float argc) else setorigin(e.enemy, e.aiment.origin + 32 * end); - e.killindicator = spawn(); - e.killindicator.classname = "drag_digit"; + e.killindicator = new(drag_digit); e.killindicator.owner = e; setattachment(e.killindicator, e, ""); setorigin(e.killindicator, '0 0 -8'); - e.killindicator.killindicator = spawn(); - e.killindicator.killindicator.classname = "drag_digit"; + e.killindicator.killindicator = new(drag_digit); e.killindicator.killindicator.owner = e; setattachment(e.killindicator.killindicator, e, ""); setorigin(e.killindicator.killindicator, '0 0 8'); @@ -457,8 +451,7 @@ float CheatCommand(float argc) } case "dragpoint_spawn": { IS_CHEAT(0, argc, 0); - entity e = spawn(); - e.classname = "dragpoint"; + entity e = new(dragpoint); e.think = DragBox_Think; e.nextthink = time; e.solid = 0; // nothing special @@ -478,13 +471,11 @@ float CheatCommand(float argc) move_out_of_solid(e); } - e.killindicator = spawn(); - e.killindicator.classname = "drag_digit"; + e.killindicator = new(drag_digit); e.killindicator.owner = e; setattachment(e.killindicator, e, ""); setorigin(e.killindicator, '0 0 40'); - e.killindicator.killindicator = spawn(); - e.killindicator.killindicator.classname = "drag_digit"; + e.killindicator.killindicator = new(drag_digit); e.killindicator.killindicator.owner = e; setattachment(e.killindicator.killindicator, e, ""); setorigin(e.killindicator.killindicator, '0 0 56'); @@ -713,9 +704,8 @@ float CheatCommand(float argc) break; case "teleporttotarget": IS_CHEAT(0, argc, 0); - setself(spawn()); + setself(new(cheattriggerteleport)); setorigin(self, self.origin); - self.classname = "cheattriggerteleport"; self.target = argv(1); teleport_findtarget(); if(!wasfreed(self)) diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 09ce11a42..8f1e3e9be 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -96,9 +96,10 @@ bool ClientData_Send(entity this, entity to, int sf) void ClientData_Attach() {SELFPARAM(); - Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send); - self.clientdata.drawonlytoclient = self; - self.clientdata.owner = self; + Net_LinkEntity(this.clientdata = new(clientdata), false, 0, ClientData_Send); + make_pure(this.clientdata); + self.clientdata.drawonlytoclient = this; + self.clientdata.owner = this; } void ClientData_Detach() @@ -535,7 +536,8 @@ void PutClientInServer() this.revival_time = 0; this.air_finished = time + 12; - entity spawnevent = spawn(); + entity spawnevent = new(spawnevent); + make_pure(spawnevent); spawnevent.owner = this; Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send); @@ -693,8 +695,9 @@ void ClientInit_CheckUpdate() void ClientInit_Spawn() {SELFPARAM(); - entity e = spawn(); - e.classname = "clientinit"; + + entity e = new(clientinit); + make_pure(e); e.think = ClientInit_CheckUpdate; Net_LinkEntity(e, false, 0, ClientInit_SendEntity); @@ -1338,7 +1341,7 @@ void UpdateChatBubble() // spawn a chatbubble entity if needed if (!self.chatbubbleentity) { - self.chatbubbleentity = spawn(); + self.chatbubbleentity = new(chatbubbleentity); self.chatbubbleentity.owner = self; self.chatbubbleentity.exteriormodeltoclient = self; self.chatbubbleentity.think = ChatBubbleThink; diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 205c2a035..83c599d72 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -52,7 +52,7 @@ void CopyBody(float keepvelocity) {SELFPARAM(); if (self.effects & EF_NODRAW) return; - setself(spawn()); + setself(new(body)); self.enemy = this; self.lip = this.lip; self.colormap = this.colormap; @@ -62,7 +62,6 @@ void CopyBody(float keepvelocity) self.angles = this.angles; self.v_angle = this.v_angle; self.avelocity = this.avelocity; - self.classname = "body"; self.damageforcescale = this.damageforcescale; self.effects = this.effects; self.glowmod = this.glowmod; diff --git a/qcsrc/server/command/radarmap.qc b/qcsrc/server/command/radarmap.qc index 26d108a1e..7475c5a54 100644 --- a/qcsrc/server/command/radarmap.qc +++ b/qcsrc/server/command/radarmap.qc @@ -372,8 +372,7 @@ float RadarMap_Make(float argc) if (!radarmapper) { - radarmapper = spawn(); - radarmapper.classname = "radarmapper"; + radarmapper = new(radarmapper); radarmapper.think = RadarMap_Think; radarmapper.nextthink = time; radarmapper.count = 8; // default to the --trace method, as it is faster now diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index c65bd8fa9..fe7b05b12 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -1000,8 +1000,7 @@ void GameCommand_make_mapinfo(float request) { entity tmp_entity; - tmp_entity = spawn(); - tmp_entity.classname = "make_mapinfo"; + tmp_entity = new(make_mapinfo); tmp_entity.think = make_mapinfo_Think; tmp_entity.nextthink = time; MapInfo_Enumerate(); diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index 1e60cd0a8..d7c829871 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -86,7 +86,8 @@ bool Nagger_SendEntity(entity this, entity to, float sendflags) void Nagger_Init() { - Net_LinkEntity(nagger = spawn(), false, 0, Nagger_SendEntity); + Net_LinkEntity(nagger = new(nagger), false, 0, Nagger_SendEntity); + make_pure(nagger); } void Nagger_VoteChanged() diff --git a/qcsrc/server/constants.qh b/qcsrc/server/constants.qh index 961b001d7..95b13f1c7 100644 --- a/qcsrc/server/constants.qh +++ b/qcsrc/server/constants.qh @@ -18,8 +18,6 @@ const int RESPAWN_SILENT = 2; #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT) -const int MSG_ENTITY = 5; // csqc - const int NUM_PLAYERSKINS_TEAMPLAY = 3; const int ASSAULT_VALUE_INACTIVE = 1000; diff --git a/qcsrc/server/ent_cs.qc b/qcsrc/server/ent_cs.qc index cf275c0f8..f69ea7a67 100644 --- a/qcsrc/server/ent_cs.qc +++ b/qcsrc/server/ent_cs.qc @@ -68,6 +68,7 @@ void entcs_think() entity attach_entcs(entity e) { entity ent = e.entcs = new(entcs_sender); + make_pure(ent); ent.owner = e; ent.think = entcs_think; ent.nextthink = time; diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 802eabd7f..36495a11c 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -49,7 +49,8 @@ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad if(!sound_allowed(MSG_BROADCAST, dmgowner)) deathtype |= 0x8000; - e = spawn(); + e = new(damageinfo); + make_pure(e); setorigin(e, org); e.projectiledeathtype = deathtype; e.dmg = coredamage; @@ -114,8 +115,7 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype) { if(!GiveFrags_randomweapons) { - GiveFrags_randomweapons = spawn(); - GiveFrags_randomweapons.classname = "GiveFrags_randomweapons"; + GiveFrags_randomweapons = new(GiveFrags_randomweapons); } if(warmup_stage) @@ -563,10 +563,8 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo targ.revive_speed = freeze_time; self.bot_attack = false; - entity ice, head; - ice = spawn(); + entity ice = new(ice); ice.owner = targ; - ice.classname = "ice"; ice.scale = targ.scale; ice.think = Ice_Think; ice.nextthink = time; @@ -582,6 +580,7 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo RemoveGrapplingHook(targ); + entity head; FOR_EACH_PLAYER(head) if(head.hook.aiment == targ) RemoveGrapplingHook(head); @@ -889,9 +888,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d vector farce = damage_explosion_calcpush(self.damageforcescale * force, self.velocity, autocvar_g_balance_damagepush_speedfactor); if(self.movetype == MOVETYPE_PHYSICS) { - entity farcent; - farcent = spawn(); - farcent.classname = "farce"; + entity farcent = new(farce); farcent.enemy = self; farcent.movedir = farce * 10; if(self.mass) @@ -1140,8 +1137,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt) if(!e.fire_burner) { // print("adding a fire burner to ", e.classname, "\n"); - e.fire_burner = spawn(); - e.fire_burner.classname = "fireburner"; + e.fire_burner = new(fireburner); e.fire_burner.think = fireburner_think; e.fire_burner.nextthink = time; e.fire_burner.owner = e; diff --git a/qcsrc/server/g_models.qc b/qcsrc/server/g_models.qc index f9f4083e3..eecb046b6 100644 --- a/qcsrc/server/g_models.qc +++ b/qcsrc/server/g_models.qc @@ -93,20 +93,20 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf) WriteByte(MSG_ENTITY, ENT_CLIENT_WALL); WriteByte(MSG_ENTITY, sf); - if(sf & 1) + if(sf & BIT(0)) { if(sf & 0x40) WriteShort(MSG_ENTITY, self.colormap); } - if(sf & 2) + if(sf & BIT(1)) { WriteCoord(MSG_ENTITY, self.origin.x); WriteCoord(MSG_ENTITY, self.origin.y); WriteCoord(MSG_ENTITY, self.origin.z); } - if(sf & 4) + if(sf & BIT(2)) { if(sf & 0x10) { @@ -116,7 +116,7 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf) } } - if(sf & 8) + if(sf & BIT(3)) { if(sf & 0x80) { diff --git a/qcsrc/server/g_violence.qc b/qcsrc/server/g_violence.qc index b016acdd6..d59c4b4da 100644 --- a/qcsrc/server/g_violence.qc +++ b/qcsrc/server/g_violence.qc @@ -2,28 +2,28 @@ .int state; +REGISTER_NET_TEMP(net_gibsplash, bool isNew) + bool Violence_GibSplash_SendEntity(entity this, entity to, int sf) { - WriteByte(MSG_ENTITY, ENT_CLIENT_GIBSPLASH); - WriteByte(MSG_ENTITY, self.state); // actually type - WriteByte(MSG_ENTITY, bound(1, self.cnt * 16, 255)); // gibbage amount multiplier - WriteShort(MSG_ENTITY, floor(self.origin.x / 4)); // not using a coord here, as gibs don't need this accuracy - WriteShort(MSG_ENTITY, floor(self.origin.y / 4)); // not using a coord here, as gibs don't need this accuracy - WriteShort(MSG_ENTITY, floor(self.origin.z / 4)); // not using a coord here, as gibs don't need this accuracy - WriteShort(MSG_ENTITY, self.oldorigin.x); // acrually compressed velocity + int channel = MSG_ONE; + msg_entity = to; + WriteHeader(channel, net_gibsplash); + WriteByte(channel, this.state); // actually type + WriteByte(channel, bound(1, this.cnt * 16, 255)); // gibbage amount multiplier + WriteShort(channel, floor(this.origin.x / 4)); // not using a coord here, as gibs don't need this accuracy + WriteShort(channel, floor(this.origin.y / 4)); // not using a coord here, as gibs don't need this accuracy + WriteShort(channel, floor(this.origin.z / 4)); // not using a coord here, as gibs don't need this accuracy + WriteShort(channel, this.oldorigin.x); // acrually compressed velocity return true; } -// TODO maybe convert this to a TE? void Violence_GibSplash_At(vector org, vector dir, float type, float amount, entity gibowner, entity attacker) {SELFPARAM(); if(g_cts) // no gibs in CTS return; - entity e; - - e = spawn(); - e.classname = "gibsplash"; + entity e = new(gibsplash); e.cnt = amount; e.state = type; // should stay smaller than 15 if(!sound_allowed(MSG_BROADCAST, gibowner) || !sound_allowed(MSG_BROADCAST, attacker)) @@ -42,7 +42,8 @@ void Violence_GibSplash_At(vector org, vector dir, float type, float amount, ent e.oldorigin_x = compressShortVector(e.velocity); - Net_LinkEntity(e, false, 0.2, Violence_GibSplash_SendEntity); + entity cl; FOR_EACH_REALCLIENT(cl) Violence_GibSplash_SendEntity(e, cl, 0); + remove(e); } void Violence_GibSplash(entity source, float type, float amount, entity attacker) diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 01e69f4be..25fcdfd00 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -83,8 +83,8 @@ void PingPLReport_Think() } void PingPLReport_Spawn() { - pingplreport = spawn(); - pingplreport.classname = "pingplreport"; + pingplreport = new(pingplreport); + make_pure(pingplreport); pingplreport.think = PingPLReport_Think; pingplreport.nextthink = time; } @@ -528,7 +528,8 @@ void RandomSeed_Think() } void RandomSeed_Spawn() {SELFPARAM(); - randomseed = spawn(); + randomseed = new(randomseed); + make_pure(randomseed); randomseed.think = RandomSeed_Think; Net_LinkEntity(randomseed, false, 0, RandomSeed_Send); @@ -546,13 +547,11 @@ spawnfunc(__init_dedicated_server) remove = remove_unsafely; - entity e; - e = spawn(); + entity e = spawn(); e.think = GotoFirstMap; e.nextthink = time; // this is usually 1 at this point - e = spawn(); - e.classname = "info_player_deathmatch"; // safeguard against player joining + e = new(info_player_deathmatch); // safeguard against player joining self.classname = "worldspawn"; // safeguard against various stuff ;) diff --git a/qcsrc/server/ipban.qc b/qcsrc/server/ipban.qc index a60970d21..7463fefbe 100644 --- a/qcsrc/server/ipban.qc +++ b/qcsrc/server/ipban.qc @@ -318,9 +318,7 @@ void Ban_LoadBans() } } - entity e; - e = spawn(); - e.classname = "bansyncer"; + entity e = new(bansyncer); e.think = OnlineBanList_Think; e.nextthink = time + 1; } diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 604e9ee43..50b578084 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -1649,10 +1649,7 @@ bool modeleffect_SendEntity(entity this, entity to, int sf) void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2) { - entity e; - float sz; - e = spawn(); - e.classname = "modeleffect"; + entity e = new(modeleffect); _setmodel(e, m); e.frame = f; setorigin(e, o); @@ -1671,7 +1668,7 @@ void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector an e.scale2 = s2 / max6(-e.mins.x, -e.mins.y, -e.mins.z, e.maxs.x, e.maxs.y, e.maxs.z); else e.scale2 = -s2; - sz = max(e.scale, e.scale2); + float sz = max(e.scale, e.scale2); setsize(e, e.mins * sz, e.maxs * sz); Net_LinkEntity(e, false, 0.1, modeleffect_SendEntity); } diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index 73e992c95..594e89b18 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -467,13 +467,12 @@ void ctf_CaptureShield_Touch() void ctf_CaptureShield_Spawn(entity flag) {SELFPARAM(); - entity shield = spawn(); + entity shield = new(ctf_captureshield); shield.enemy = self; shield.team = self.team; shield.touch = ctf_CaptureShield_Touch; shield.customizeentityforclient = ctf_CaptureShield_Customize; - shield.classname = "ctf_captureshield"; shield.effects = EF_ADDITIVE; shield.movetype = MOVETYPE_NOCLIP; shield.solid = SOLID_TRIGGER; diff --git a/qcsrc/server/mutators/mutator/gamemode_keepaway.qc b/qcsrc/server/mutators/mutator/gamemode_keepaway.qc index 8961e6bf0..ea1424370 100644 --- a/qcsrc/server/mutators/mutator/gamemode_keepaway.qc +++ b/qcsrc/server/mutators/mutator/gamemode_keepaway.qc @@ -462,13 +462,11 @@ MUTATOR_HOOKFUNCTION(ka, DropSpecialItems) void ka_SpawnBall() // loads various values for the ball, runs only once at start of match { - entity e; - e = spawn(); + entity e = new(keepawayball); e.model = "models/orbs/orbblue.md3"; precache_model(e.model); _setmodel(e, e.model); setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off - e.classname = "keepawayball"; e.damageforcescale = autocvar_g_keepawayball_damageforcescale; e.takedamage = DAMAGE_YES; e.solid = SOLID_TRIGGER; diff --git a/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc b/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc index 5982cf208..6f46cef37 100644 --- a/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc +++ b/qcsrc/server/mutators/mutator/gamemode_keyhunt.qc @@ -802,8 +802,7 @@ void key_reset() const string STR_ITEM_KH_KEY = "item_kh_key"; void kh_Key_Spawn(entity initial_owner, float angle, float i) // runs every time a new flag is created, ie after all the keys have been collected { - entity key; - key = spawn(); + entity key = spawn(); key.count = i; key.classname = STR_ITEM_KH_KEY; key.touch = kh_Key_Touch; diff --git a/qcsrc/server/mutators/mutator/gamemode_onslaught.qc b/qcsrc/server/mutators/mutator/gamemode_onslaught.qc index 51ddcadf9..02f1dffbc 100644 --- a/qcsrc/server/mutators/mutator/gamemode_onslaught.qc +++ b/qcsrc/server/mutators/mutator/gamemode_onslaught.qc @@ -203,7 +203,7 @@ void ons_CaptureShield_Reset() void ons_CaptureShield_Spawn(entity generator, bool is_generator) { - entity shield = spawn(); + entity shield = new(ons_captureshield); shield.enemy = generator; shield.team = generator.team; @@ -211,7 +211,6 @@ void ons_CaptureShield_Spawn(entity generator, bool is_generator) shield.reset = ons_CaptureShield_Reset; shield.touch = ons_CaptureShield_Touch; shield.customizeentityforclient = ons_CaptureShield_Customize; - shield.classname = "ons_captureshield"; shield.effects = EF_ADDITIVE; shield.movetype = MOVETYPE_NOCLIP; shield.solid = SOLID_TRIGGER; @@ -712,12 +711,11 @@ void onslaught_controlpoint_icon_link(entity e, void() spawnproc); void ons_ControlPoint_Icon_Spawn(entity cp, entity player) { - entity e = spawn(); + entity e = new(onslaught_controlpoint_icon); setsize(e, CPICON_MIN, CPICON_MAX); setorigin(e, cp.origin + CPICON_OFFSET); - e.classname = "onslaught_controlpoint_icon"; e.owner = cp; e.max_health = autocvar_g_onslaught_cp_health; e.health = autocvar_g_onslaught_cp_buildhealth; diff --git a/qcsrc/server/mutators/mutator/mutator_nades.qc b/qcsrc/server/mutators/mutator/mutator_nades.qc index cc567d2b8..ccbf9e3ee 100644 --- a/qcsrc/server/mutators/mutator/mutator_nades.qc +++ b/qcsrc/server/mutators/mutator/mutator_nades.qc @@ -69,10 +69,9 @@ void nade_burn_spawn(entity _nade) void nade_spawn(entity _nade) { - entity timer = spawn(); + entity timer = new(nade_timer); setmodel(timer, MDL_NADE_TIMER); setattachment(timer, _nade, ""); - timer.classname = "nade_timer"; timer.colormap = _nade.colormap; timer.glowmod = _nade.glowmod; timer.think = nade_timer_think; @@ -164,11 +163,10 @@ void nade_napalm_ball() spamsound(self, CH_SHOTS, SND(FIREBALL_FIRE), VOL_BASE, ATTEN_NORM); - proj = spawn (); + proj = new(grenade); proj.owner = self.owner; proj.realowner = self.realowner; proj.team = self.owner.team; - proj.classname = "grenade"; proj.bot_dodge = true; proj.bot_dodgerating = autocvar_g_nades_napalm_ball_damage; proj.movetype = MOVETYPE_BOUNCE; @@ -360,10 +358,9 @@ void nade_ice_boom() if ( autocvar_g_nades_ice_explode ) { setmodel(fountain, MDL_PROJECTILE_GRENADE); - entity timer = spawn(); + entity timer = new(nade_timer); setmodel(timer, MDL_NADE_TIMER); setattachment(timer, fountain, ""); - timer.classname = "nade_timer"; timer.colormap = self.colormap; timer.glowmod = self.glowmod; timer.think = nade_timer_think; @@ -827,10 +824,7 @@ void nade_prime() if(self.fake_nade) remove(self.fake_nade); - entity n = spawn(), fn = spawn(); - - n.classname = "nade"; - fn.classname = "fake_nade"; + entity n = new(nade), fn = new(fake_nade); if(self.items & ITEM_Strength.m_itemid && autocvar_g_nades_bonus_onstrength) n.nade_type = self.nade_type; diff --git a/qcsrc/server/mutators/mutator/mutator_overkill.qc b/qcsrc/server/mutators/mutator/mutator_overkill.qc index 0df6accdd..017a8a2e9 100644 --- a/qcsrc/server/mutators/mutator/mutator_overkill.qc +++ b/qcsrc/server/mutators/mutator/mutator_overkill.qc @@ -108,7 +108,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies) other = world; } - setself(spawn()); + setself(new(droppedweapon)); // hax self.ok_item = true; self.noalign = true; self.pickup_anyway = true; @@ -118,7 +118,6 @@ MUTATOR_HOOKFUNCTION(ok, PlayerDies) self.reset = SUB_Remove; setorigin(self, frag_target.origin + '0 0 32'); self.velocity = '0 0 200' + normalize(targ.origin - self.origin) * 500; - self.classname = "droppedweapon"; // hax SUB_SetFade(self, time + 5, 1); setself(this); @@ -247,10 +246,9 @@ MUTATOR_HOOKFUNCTION(ok, OnEntityPreSpawn) { if(self.classname == "item_strength") { - entity wep = spawn(); + entity wep = new(weapon_hmg); setorigin(wep, self.origin); setmodel(wep, MDL_OK_HMG); - wep.classname = "weapon_hmg"; wep.ok_item = true; wep.noalign = self.noalign; wep.cnt = self.cnt; @@ -264,10 +262,9 @@ MUTATOR_HOOKFUNCTION(ok, OnEntityPreSpawn) if(self.classname == "item_invincible") { - entity wep = spawn(); + entity wep = new(weapon_rpc); setorigin(wep, self.origin); setmodel(wep, MDL_OK_RPC); - wep.classname = "weapon_rpc"; wep.ok_item = true; wep.noalign = self.noalign; wep.cnt = self.cnt; diff --git a/qcsrc/server/mutators/mutator/sandbox.qc b/qcsrc/server/mutators/mutator/sandbox.qc index dbee6a137..9369da457 100644 --- a/qcsrc/server/mutators/mutator/sandbox.qc +++ b/qcsrc/server/mutators/mutator/sandbox.qc @@ -165,8 +165,7 @@ entity sandbox_ObjectSpawn(float database) {SELFPARAM(); // spawn a new object with default properties - entity e = spawn(); - e.classname = "object"; + entity e = new(object); e.takedamage = DAMAGE_AIM; e.damageforcescale = 1; e.solid = SOLID_BBOX; // SOLID_BSP would be best, but can lag the server badly diff --git a/qcsrc/server/pathlib/main.qc b/qcsrc/server/pathlib/main.qc index 800f0335e..9a199bd62 100644 --- a/qcsrc/server/pathlib/main.qc +++ b/qcsrc/server/pathlib/main.qc @@ -471,9 +471,8 @@ entity pathlib_astar(vector from,vector to) { LOG_TRACE("AStar: Goal found on first node!\n"); - open = spawn(); + open = new(path_end); open.owner = open; - open.classname = "path_end"; setorigin(open,path.origin); pathlib_cleanup(); diff --git a/qcsrc/server/portals.qc b/qcsrc/server/portals.qc index 9b1d7194f..186004637 100644 --- a/qcsrc/server/portals.qc +++ b/qcsrc/server/portals.qc @@ -624,8 +624,7 @@ entity Portal_Spawn(entity own, vector org, vector ang) if(!CheckWireframeBox(own, org - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward)) return world; - portal = spawn(); - portal.classname = "portal"; + portal = new(portal); portal.aiment = own; setorigin(portal, org); portal.mangle = ang; diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 678baec95..8e4ae3040 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -87,9 +87,8 @@ bool TeamScore_SendEntity(entity this, entity to, float sendflags) void TeamScore_Spawn(float t, string name) { - entity ts; - ts = spawn(); - ts.classname = "csqc_score_team"; + entity ts = new(csqc_score_team); + make_pure(ts); ts.netname = name; // not used yet, FIXME ts.team = t; Net_LinkEntity(ts, false, 0, TeamScore_SendEntity); @@ -211,8 +210,8 @@ void ScoreInfo_Init(float teams) } else { - scores_initialized = spawn(); - scores_initialized.classname = "ent_client_scoreinfo"; + scores_initialized = new(ent_client_scoreinfo); + make_pure(scores_initialized); Net_LinkEntity(scores_initialized, false, 0, ScoreInfo_SendEntity); } if(teams >= 1) @@ -316,10 +315,10 @@ void Score_ClearAll() void PlayerScore_Attach(entity player) { - entity sk; if(player.scorekeeper) error("player already has a scorekeeper"); - sk = spawn(); + entity sk = new(scorekeeper); + make_pure(sk); sk.owner = player; Net_LinkEntity(sk, false, 0, PlayerScore_SendEntity); player.scorekeeper = sk; diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index a1abfa58f..ecd7497d9 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -117,9 +117,7 @@ void relocate_spawnpoint() { // show where spawnpoints point at too makevectors(self.angles); - entity e; - e = spawn(); - e.classname = "info_player_foo"; + entity e = new(info_player_foo); setorigin(e, self.origin + v_forward * 24); setsize(e, '-8 -8 -8', '8 8 8'); e.solid = SOLID_TRIGGER; diff --git a/qcsrc/server/steerlib.qc b/qcsrc/server/steerlib.qc index 4941b5521..beaab08a4 100644 --- a/qcsrc/server/steerlib.qc +++ b/qcsrc/server/steerlib.qc @@ -547,16 +547,13 @@ MODEL(FLOCKER, "models/turrets/rocket.md3"); void spawn_flocker() {SELFPARAM(); - entity flocker; - - flocker = spawn (); + entity flocker = new(flocker); setorigin(flocker, self.origin + '0 0 32'); setmodel (flocker, MDL_FLOCKER); setsize (flocker, '-3 -3 -3', '3 3 3'); flocker.flock_id = self.flock_id; - flocker.classname = "flocker"; flocker.owner = self; flocker.think = flocker_think; flocker.nextthink = time + random() * 5; @@ -649,12 +646,11 @@ spawnfunc(flockerspawn) self.think = flockerspawn_think; self.nextthink = time + 0.25; - self.enemy = spawn(); + self.enemy = new(FLock Hunter); setmodel(self.enemy, MDL_FLOCKER); setorigin(self.enemy,self.origin + '0 0 768' + (randomvec() * 128)); - self.enemy.classname = "FLock Hunter"; self.enemy.scale = 3; self.enemy.effects = EF_LOWPRECISION; self.enemy.movetype = MOVETYPE_BOUNCEMISSILE; diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index 1ffcb60c5..7dbc6148a 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -13,6 +13,7 @@ #include "../common/constants.qh" #include "../common/deathtypes/all.qh" +#include "../common/debug.qh" #include "../common/mapinfo.qh" #include "../common/util.qh" diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc index f8bc6a1a1..019bcda49 100644 --- a/qcsrc/server/weapons/accuracy.qc +++ b/qcsrc/server/weapons/accuracy.qc @@ -40,6 +40,7 @@ bool accuracy_send(entity this, entity to, int sf) void accuracy_init(entity e) { entity a = e.accuracy = new(accuracy); + make_pure(a); a.owner = e; a.drawonlytoclient = e; Net_LinkEntity(a, false, 0, accuracy_send); diff --git a/qcsrc/server/weapons/throwing.qc b/qcsrc/server/weapons/throwing.qc index 900b45018..067018373 100644 --- a/qcsrc/server/weapons/throwing.qc +++ b/qcsrc/server/weapons/throwing.qc @@ -36,10 +36,9 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto string s; var .int ammotype = (get_weaponinfo(wpn)).ammo_field; - entity wep = spawn(); + entity wep = new(droppedweapon); setorigin(wep, org); - wep.classname = "droppedweapon"; wep.velocity = velo; wep.owner = wep.enemy = own; wep.flags |= FL_TOSSED; diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index e64391d83..ff8743033 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -175,13 +175,13 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) // if we don't, this is a "real" animated model if (gettagindex(this, "weapon")) { - if (!this.weaponentity[slot]) this.weaponentity[slot] = spawn(); + if (!this.weaponentity[slot]) this.weaponentity[slot] = new(weaponentity); _setmodel(this.weaponentity[slot], W_Model(strcat("v_", name, ".md3"))); setattachment(this.weaponentity[slot], this, "weapon"); } else if (gettagindex(this, "tag_weapon")) { - if (!this.weaponentity[slot]) this.weaponentity[slot] = spawn(); + if (!this.weaponentity[slot]) this.weaponentity[slot] = new(weaponentity); _setmodel(this.weaponentity[slot], W_Model(strcat("v_", name, ".md3"))); setattachment(this.weaponentity[slot], this, "tag_weapon"); } @@ -442,6 +442,7 @@ void CL_ExteriorWeaponentity_Think() void CL_SpawnWeaponentity(entity e, int slot) { entity view = e.weaponentity[slot] = new(weaponentity); + make_pure(view); view.solid = SOLID_NOT; view.owner = e; setmodel(view, MDL_Null); // precision set when changed @@ -455,8 +456,8 @@ void CL_SpawnWeaponentity(entity e, int slot) if (slot == 0) { - entity exterior = e.exteriorweaponentity = spawn(); - exterior.classname = "exteriorweaponentity"; + entity exterior = e.exteriorweaponentity = new(exteriorweaponentity); + make_pure(exterior); exterior.solid = SOLID_NOT; exterior.exteriorweaponentity = exterior; exterior.owner = e; -- 2.39.2