summaryrefslogtreecommitdiff
path: root/src/fpsgame/entities.cpp
diff options
context:
space:
mode:
authorxolatile2025-08-04 22:53:42 +0200
committerxolatile2025-08-04 22:53:42 +0200
commitd309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch)
tree999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/fpsgame/entities.cpp
parent29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff)
downloadxolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz
xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst
Bunch of small changes...
Diffstat (limited to 'src/fpsgame/entities.cpp')
-rw-r--r--src/fpsgame/entities.cpp886
1 files changed, 443 insertions, 443 deletions
diff --git a/src/fpsgame/entities.cpp b/src/fpsgame/entities.cpp
index 4676ca8..dc0e175 100644
--- a/src/fpsgame/entities.cpp
+++ b/src/fpsgame/entities.cpp
@@ -4,456 +4,456 @@ int pwitemspicked[7] = { 0 };
namespace entities
{
- using namespace game;
+ using namespace game;
- int extraentinfosize() { return 0; } // size in bytes of what the 2 methods below read/write... so it can be skipped by other games
+ int extraentinfosize() { return 0; } // size in bytes of what the 2 methods below read/write... so it can be skipped by other games
- void writeent(entity &e, char *buf) // write any additional data to disk (except for ET_ ents)
- {
- }
+ void writeent(entity &e, char *buf) // write any additional data to disk (except for ET_ ents)
+ {
+ }
- void readent(entity &e, char *buf, int ver) // read from disk, and init
- {
- if(ver <= 30) switch(e.type)
- {
- case TELEDEST:
- e.attr1 = (int(e.attr1)+180)%360;
- break;
- }
- }
+ void readent(entity &e, char *buf, int ver) // read from disk, and init
+ {
+ if(ver <= 30) switch(e.type)
+ {
+ case TELEDEST:
+ e.attr1 = (int(e.attr1)+180)%360;
+ break;
+ }
+ }
#ifndef STANDALONE
- vector<extentity *> ents;
-
- vector<extentity *> &getents() { return ents; }
-
- bool mayattach(extentity &e) { return false; }
- bool attachent(extentity &e, extentity &a) { return false; }
-
- const char *itemname(int i)
- {
- int t = ents[i]->type;
- if(t<I_SHELLS || t>I_QUAD) return NULL;
- return itemstats[t-I_SHELLS].name;
- }
-
- int itemicon(int i)
- {
- int t = ents[i]->type;
- if(t<I_SHELLS || t>I_QUAD) return -1;
- return itemstats[t-I_SHELLS].icon;
- }
-
- const char *entmdlname(int type)
- {
- static const char * const entmdlnames[] =
- {
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "ammo/shells", "ammo/bullets", "ammo/rockets", "ammo/rrounds", "ammo/grenades", "ammo/cartridges",
- "health", "boost", "tinyhealth", "tinyarmour", "armor/green", "armor/yellow", "quad", "teleporter",
- NULL, NULL,
- "carrot",
- NULL, NULL,
- "checkpoint",
- NULL, NULL,
- NULL, NULL,
- NULL
- };
- return entmdlnames[type];
- }
-
- const char *entmodel(const entity &e)
- {
- if(e.type == TELEPORT)
- {
- if(e.attr2 > 0) return mapmodelname(e.attr2);
- if(e.attr2 < 0) return NULL;
- }
- return e.type < MAXENTTYPES ? entmdlname(e.type) : NULL;
- }
-
- void preloadentities()
- {
- loopi(MAXENTTYPES)
- {
- switch(i)
- {
- case I_SHELLS:
- [[fallthrough]];
- case I_BULLETS:
- [[fallthrough]];
- case I_ROCKETS:
- [[fallthrough]];
- case I_ROUNDS:
- [[fallthrough]];
- case I_GRENADES:
- [[fallthrough]];
- case I_CARTRIDGES:
- if(m_noammo) continue;
- break;
- case I_HEALTH:
- [[fallthrough]];
- case I_BOOST:
- [[fallthrough]];
- case I_TINYHEALTH:
- [[fallthrough]];
- case I_TINYARMOUR:
- [[fallthrough]];
- case I_GREENARMOUR:
- [[fallthrough]];
- case I_YELLOWARMOUR:
- [[fallthrough]];
- case I_QUAD:
- if(m_noitems) continue;
- break;
- }
- const char *mdl = entmdlname(i);
- if(!mdl) continue;
- preloadmodel(mdl);
- }
- loopv(ents)
- {
- extentity &e = *ents[i];
- switch(e.type)
- {
- case TELEPORT:
- if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2));
- [[fallthrough]];
-
- case JUMPPAD:
- if(e.attr4 > 0) preloadmapsound(e.attr4);
- break;
- }
- }
- }
-
- void renderentities()
- {
- loopv(ents)
- {
- extentity &e = *ents[i];
- int revs = 10;
- switch(e.type)
- {
- case TELEPORT:
- if(e.attr2 < 0) continue;
- break;
- default:
- if(!e.spawned() || e.type < I_SHELLS || e.type > I_QUAD) continue;
- }
- const char *mdlname = entmodel(e);
- if(mdlname)
- {
- vec p = e.o;
- p.z += 1+sinf(lastmillis/100.0+e.o.x+e.o.y)/20;
- rendermodel(&e.light, mdlname, ANIM_MAPMODEL|ANIM_LOOP, p, lastmillis/(float)revs, 0, MDL_SHADOW | MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
- }
- }
- }
-
- void addammo(int type, int &v, bool local)
- {
- itemstat &is = itemstats[type-I_SHELLS];
- v += is.add;
- if(v>is.max) v = is.max;
- if(local) msgsound(is.sound);
- }
-
- void repammo(fpsent *d, int type, bool local)
- {
- addammo(type, d->ammo[type-I_SHELLS+GUN_SG], local);
- }
-
- // these two functions are called when the server acknowledges that you really
- // picked up the item (in multiplayer someone may grab it before you).
-
- void pickupeffects(int n, fpsent *d)
- {
- if(!ents.inrange(n)) return;
- extentity *e = ents[n];
- int type = e->type;
- if(type<I_SHELLS || type>I_QUAD) return;
- e->clearspawned();
- e->clearnopickup();
- if(!d) return;
- itemstat &is = itemstats[type-I_SHELLS];
- fpsent *h = followingplayer(player1);
- if(d!=h || isthirdperson())
- {
- //particle_text(d->abovehead(), is.name, PART_TEXT, 2000, 0xFFC864, 4.0f, -8);
- particle_icon(d->abovehead(), is.icon%4, is.icon/4, PART_HUD_ICON_GREY, 2000, 0xFFFFFF, 2.0f, -8);
- }
- playsound(itemstats[type-I_SHELLS].sound, d!=h ? &d->o : NULL, NULL, 0, 0, 0, -1, 0, 1500);
- d->pickup(type);
- switch(type) {
- case I_TINYARMOUR: pwitemspicked[0]++; break;
- case I_GREENARMOUR: pwitemspicked[1]++; break;
- case I_YELLOWARMOUR: pwitemspicked[2]++; break;
- case I_TINYHEALTH: pwitemspicked[3]++; break;
- case I_HEALTH: pwitemspicked[4]++; break;
- case I_BOOST: pwitemspicked[5]++; break;
- case I_QUAD: pwitemspicked[6]++; break;
- }
- if(d==h) switch(type)
- {
- case I_BOOST:
- conoutf(CON_GAMEINFO, "\f2you got the health boost!");
- playsound(S_V_BOOST, NULL, NULL, 0, 0, 0, -1, 0, 3000);
- break;
-
- case I_QUAD:
- conoutf(CON_GAMEINFO, "\f2you got the quad!");
- playsound(S_V_QUAD, NULL, NULL, 0, 0, 0, -1, 0, 3000);
- break;
- }
- }
-
- // these functions are called when the client touches the item
-
- void teleporteffects(fpsent *d, int tp, int td, bool local)
- {
- if(ents.inrange(tp) && ents[tp]->type == TELEPORT)
- {
- extentity &e = *ents[tp];
- if(e.attr4 >= 0)
- {
- int snd = S_TELEPORT, flags = 0;
- if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; }
- fpsent *h = followingplayer(player1);
- playsound(snd, d==h ? NULL : &e.o, NULL, flags);
- if(d!=h && ents.inrange(td) && ents[td]->type == TELEDEST) playsound(snd, &ents[td]->o, NULL, flags);
- }
- }
- if(local && d->clientnum >= 0)
- {
- sendposition(d);
- packetbuf p(32, ENET_PACKET_FLAG_RELIABLE);
- putint(p, N_TELEPORT);
- putint(p, d->clientnum);
- putint(p, tp);
- putint(p, td);
- sendclientpacket(p.finalize(), 0);
- flushclient();
- }
- }
-
- void jumppadeffects(fpsent *d, int jp, bool local)
- {
- if(ents.inrange(jp) && ents[jp]->type == JUMPPAD)
- {
- extentity &e = *ents[jp];
- if(e.attr4 >= 0)
- {
- int snd = S_JUMPPAD, flags = 0;
- if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; }
- playsound(snd, d == followingplayer(player1) ? NULL : &e.o, NULL, flags);
- }
- }
- if(local && d->clientnum >= 0)
- {
- sendposition(d);
- packetbuf p(16, ENET_PACKET_FLAG_RELIABLE);
- putint(p, N_JUMPPAD);
- putint(p, d->clientnum);
- putint(p, jp);
- sendclientpacket(p.finalize(), 0);
- flushclient();
- }
- }
-
- void teleport(int n, fpsent *d) // also used by monsters
- {
- int e = -1, tag = ents[n]->attr1, beenhere = -1;
- for(;;)
- {
- e = findentity(TELEDEST, e+1);
- if(e==beenhere || e<0) { conoutf(CON_WARN, "no teleport destination for tag %d", tag); return; }
- if(beenhere<0) beenhere = e;
- if(ents[e]->attr2==tag)
- {
- teleporteffects(d, n, e, true);
- d->o = ents[e]->o;
- d->yaw = ents[e]->attr1;
- if(ents[e]->attr3 > 0)
- {
- vec dir;
- vecfromyawpitch(d->yaw, 0, 1, 0, dir);
- float speed = d->vel.magnitude2();
- d->vel.x = dir.x*speed;
- d->vel.y = dir.y*speed;
- }
- else d->vel = vec(0, 0, 0);
- entinmap(d);
- updatedynentcache(d);
- ai::inferwaypoints(d, ents[n]->o, ents[e]->o, 16.f);
- break;
- }
- }
- }
-
- void trypickup(int n, fpsent *d)
- {
- extentity *e = ents[n];
- switch(e->type)
- {
- default:
- if(d->canpickup(e->type))
- {
- addmsg(N_ITEMPICKUP, "rci", d, n);
- e->setnopickup(); // even if someone else gets it first
- }
- break;
-
- case TELEPORT:
- {
- if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<500) break;
- if(e->attr3 > 0)
- {
- defformatstring(hookname, "can_teleport_%d", e->attr3);
- if(!execidentbool(hookname, true)) break;
- }
- d->lastpickup = e->type;
- d->lastpickupmillis = lastmillis;
- teleport(n, d);
- break;
- }
-
- case JUMPPAD:
- {
- if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<300) break;
- d->lastpickup = e->type;
- d->lastpickupmillis = lastmillis;
- jumppadeffects(d, n, true);
- vec v((int)(char)e->attr3*10.0f, (int)(char)e->attr2*10.0f, e->attr1*12.5f);
- if(d->ai) d->ai->becareful = true;
+ vector<extentity *> ents;
+
+ vector<extentity *> &getents() { return ents; }
+
+ bool mayattach(extentity &e) { return false; }
+ bool attachent(extentity &e, extentity &a) { return false; }
+
+ const char *itemname(int i)
+ {
+ int t = ents[i]->type;
+ if(t<I_SHELLS || t>I_QUAD) return NULL;
+ return itemstats[t-I_SHELLS].name;
+ }
+
+ int itemicon(int i)
+ {
+ int t = ents[i]->type;
+ if(t<I_SHELLS || t>I_QUAD) return -1;
+ return itemstats[t-I_SHELLS].icon;
+ }
+
+ const char *entmdlname(int type)
+ {
+ static const char * const entmdlnames[] =
+ {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ "ammo/shells", "ammo/bullets", "ammo/rockets", "ammo/rrounds", "ammo/grenades", "ammo/cartridges",
+ "health", "boost", "tinyhealth", "tinyarmour", "armor/green", "armor/yellow", "quad", "teleporter",
+ NULL, NULL,
+ "carrot",
+ NULL, NULL,
+ "checkpoint",
+ NULL, NULL,
+ NULL, NULL,
+ NULL
+ };
+ return entmdlnames[type];
+ }
+
+ const char *entmodel(const entity &e)
+ {
+ if(e.type == TELEPORT)
+ {
+ if(e.attr2 > 0) return mapmodelname(e.attr2);
+ if(e.attr2 < 0) return NULL;
+ }
+ return e.type < MAXENTTYPES ? entmdlname(e.type) : NULL;
+ }
+
+ void preloadentities()
+ {
+ loopi(MAXENTTYPES)
+ {
+ switch(i)
+ {
+ case I_SHELLS:
+ [[fallthrough]];
+ case I_BULLETS:
+ [[fallthrough]];
+ case I_ROCKETS:
+ [[fallthrough]];
+ case I_ROUNDS:
+ [[fallthrough]];
+ case I_GRENADES:
+ [[fallthrough]];
+ case I_CARTRIDGES:
+ if(m_noammo) continue;
+ break;
+ case I_HEALTH:
+ [[fallthrough]];
+ case I_BOOST:
+ [[fallthrough]];
+ case I_TINYHEALTH:
+ [[fallthrough]];
+ case I_TINYARMOUR:
+ [[fallthrough]];
+ case I_GREENARMOUR:
+ [[fallthrough]];
+ case I_YELLOWARMOUR:
+ [[fallthrough]];
+ case I_QUAD:
+ if(m_noitems) continue;
+ break;
+ }
+ const char *mdl = entmdlname(i);
+ if(!mdl) continue;
+ preloadmodel(mdl);
+ }
+ loopv(ents)
+ {
+ extentity &e = *ents[i];
+ switch(e.type)
+ {
+ case TELEPORT:
+ if(e.attr2 > 0) preloadmodel(mapmodelname(e.attr2));
+ [[fallthrough]];
+
+ case JUMPPAD:
+ if(e.attr4 > 0) preloadmapsound(e.attr4);
+ break;
+ }
+ }
+ }
+
+ void renderentities()
+ {
+ loopv(ents)
+ {
+ extentity &e = *ents[i];
+ int revs = 10;
+ switch(e.type)
+ {
+ case TELEPORT:
+ if(e.attr2 < 0) continue;
+ break;
+ default:
+ if(!e.spawned() || e.type < I_SHELLS || e.type > I_QUAD) continue;
+ }
+ const char *mdlname = entmodel(e);
+ if(mdlname)
+ {
+ vec p = e.o;
+ p.z += 1+sinf(lastmillis/100.0+e.o.x+e.o.y)/20;
+ rendermodel(&e.light, mdlname, ANIM_MAPMODEL|ANIM_LOOP, p, lastmillis/(float)revs, 0, MDL_SHADOW | MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
+ }
+ }
+ }
+
+ void addammo(int type, int &v, bool local)
+ {
+ itemstat &is = itemstats[type-I_SHELLS];
+ v += is.add;
+ if(v>is.max) v = is.max;
+ if(local) msgsound(is.sound);
+ }
+
+ void repammo(fpsent *d, int type, bool local)
+ {
+ addammo(type, d->ammo[type-I_SHELLS+GUN_SG], local);
+ }
+
+ // these two functions are called when the server acknowledges that you really
+ // picked up the item (in multiplayer someone may grab it before you).
+
+ void pickupeffects(int n, fpsent *d)
+ {
+ if(!ents.inrange(n)) return;
+ extentity *e = ents[n];
+ int type = e->type;
+ if(type<I_SHELLS || type>I_QUAD) return;
+ e->clearspawned();
+ e->clearnopickup();
+ if(!d) return;
+ itemstat &is = itemstats[type-I_SHELLS];
+ fpsent *h = followingplayer(player1);
+ if(d!=h || isthirdperson())
+ {
+ //particle_text(d->abovehead(), is.name, PART_TEXT, 2000, 0xFFC864, 4.0f, -8);
+ particle_icon(d->abovehead(), is.icon%4, is.icon/4, PART_HUD_ICON_GREY, 2000, 0xFFFFFF, 2.0f, -8);
+ }
+ playsound(itemstats[type-I_SHELLS].sound, d!=h ? &d->o : NULL, NULL, 0, 0, 0, -1, 0, 1500);
+ d->pickup(type);
+ switch(type) {
+ case I_TINYARMOUR: pwitemspicked[0]++; break;
+ case I_GREENARMOUR: pwitemspicked[1]++; break;
+ case I_YELLOWARMOUR: pwitemspicked[2]++; break;
+ case I_TINYHEALTH: pwitemspicked[3]++; break;
+ case I_HEALTH: pwitemspicked[4]++; break;
+ case I_BOOST: pwitemspicked[5]++; break;
+ case I_QUAD: pwitemspicked[6]++; break;
+ }
+ if(d==h) switch(type)
+ {
+ case I_BOOST:
+ conoutf(CON_GAMEINFO, "\f2you got the health boost!");
+ playsound(S_V_BOOST, NULL, NULL, 0, 0, 0, -1, 0, 3000);
+ break;
+
+ case I_QUAD:
+ conoutf(CON_GAMEINFO, "\f2you got the quad!");
+ playsound(S_V_QUAD, NULL, NULL, 0, 0, 0, -1, 0, 3000);
+ break;
+ }
+ }
+
+ // these functions are called when the client touches the item
+
+ void teleporteffects(fpsent *d, int tp, int td, bool local)
+ {
+ if(ents.inrange(tp) && ents[tp]->type == TELEPORT)
+ {
+ extentity &e = *ents[tp];
+ if(e.attr4 >= 0)
+ {
+ int snd = S_TELEPORT, flags = 0;
+ if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; }
+ fpsent *h = followingplayer(player1);
+ playsound(snd, d==h ? NULL : &e.o, NULL, flags);
+ if(d!=h && ents.inrange(td) && ents[td]->type == TELEDEST) playsound(snd, &ents[td]->o, NULL, flags);
+ }
+ }
+ if(local && d->clientnum >= 0)
+ {
+ sendposition(d);
+ packetbuf p(32, ENET_PACKET_FLAG_RELIABLE);
+ putint(p, N_TELEPORT);
+ putint(p, d->clientnum);
+ putint(p, tp);
+ putint(p, td);
+ sendclientpacket(p.finalize(), 0);
+ flushclient();
+ }
+ }
+
+ void jumppadeffects(fpsent *d, int jp, bool local)
+ {
+ if(ents.inrange(jp) && ents[jp]->type == JUMPPAD)
+ {
+ extentity &e = *ents[jp];
+ if(e.attr4 >= 0)
+ {
+ int snd = S_JUMPPAD, flags = 0;
+ if(e.attr4 > 0) { snd = e.attr4; flags = SND_MAP; }
+ playsound(snd, d == followingplayer(player1) ? NULL : &e.o, NULL, flags);
+ }
+ }
+ if(local && d->clientnum >= 0)
+ {
+ sendposition(d);
+ packetbuf p(16, ENET_PACKET_FLAG_RELIABLE);
+ putint(p, N_JUMPPAD);
+ putint(p, d->clientnum);
+ putint(p, jp);
+ sendclientpacket(p.finalize(), 0);
+ flushclient();
+ }
+ }
+
+ void teleport(int n, fpsent *d) // also used by monsters
+ {
+ int e = -1, tag = ents[n]->attr1, beenhere = -1;
+ for(;;)
+ {
+ e = findentity(TELEDEST, e+1);
+ if(e==beenhere || e<0) { conoutf(CON_WARN, "no teleport destination for tag %d", tag); return; }
+ if(beenhere<0) beenhere = e;
+ if(ents[e]->attr2==tag)
+ {
+ teleporteffects(d, n, e, true);
+ d->o = ents[e]->o;
+ d->yaw = ents[e]->attr1;
+ if(ents[e]->attr3 > 0)
+ {
+ vec dir;
+ vecfromyawpitch(d->yaw, 0, 1, 0, dir);
+ float speed = d->vel.magnitude2();
+ d->vel.x = dir.x*speed;
+ d->vel.y = dir.y*speed;
+ }
+ else d->vel = vec(0, 0, 0);
+ entinmap(d);
+ updatedynentcache(d);
+ ai::inferwaypoints(d, ents[n]->o, ents[e]->o, 16.f);
+ break;
+ }
+ }
+ }
+
+ void trypickup(int n, fpsent *d)
+ {
+ extentity *e = ents[n];
+ switch(e->type)
+ {
+ default:
+ if(d->canpickup(e->type))
+ {
+ addmsg(N_ITEMPICKUP, "rci", d, n);
+ e->setnopickup(); // even if someone else gets it first
+ }
+ break;
+
+ case TELEPORT:
+ {
+ if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<500) break;
+ if(e->attr3 > 0)
+ {
+ defformatstring(hookname, "can_teleport_%d", e->attr3);
+ if(!execidentbool(hookname, true)) break;
+ }
+ d->lastpickup = e->type;
+ d->lastpickupmillis = lastmillis;
+ teleport(n, d);
+ break;
+ }
+
+ case JUMPPAD:
+ {
+ if(d->lastpickup==e->type && lastmillis-d->lastpickupmillis<300) break;
+ d->lastpickup = e->type;
+ d->lastpickupmillis = lastmillis;
+ jumppadeffects(d, n, true);
+ vec v((int)(char)e->attr3*10.0f, (int)(char)e->attr2*10.0f, e->attr1*12.5f);
+ if(d->ai) d->ai->becareful = true;
d->falling = vec(0, 0, 0);
d->physstate = PHYS_FALL;
- d->timeinair = 1;
- d->vel = v;
- break;
- }
- }
- }
-
- void checkitems(fpsent *d)
- {
- if(d->state!=CS_ALIVE) return;
- vec o = d->feetpos();
- loopv(ents)
- {
- extentity &e = *ents[i];
- if(e.type==NOTUSED) continue;
- if((!e.spawned() || e.nopickup()) && e.type!=TELEPORT && e.type!=JUMPPAD) continue;
- float dist = e.o.dist(o);
- if(dist<(e.type==TELEPORT ? 16 : 12)) trypickup(i, d);
- }
- }
-
- void checkquad(int time, fpsent *d)
- {
- if(d->quadmillis && (d->quadmillis -= time)<=0)
- {
- d->quadmillis = 0;
- fpsent *h = followingplayer(player1);
- playsound(S_PUPOUT, d==h ? NULL : &d->o);
- if(d==h) conoutf(CON_GAMEINFO, "\f2quad damage is over");
- }
- }
-
- void putitems(packetbuf &p) // puts items in network stream and also spawns them locally
- {
- putint(p, N_ITEMLIST);
- loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->type<I_SHELLS || ents[i]->type>I_CARTRIDGES))
- {
- putint(p, i);
- putint(p, ents[i]->type);
- }
- putint(p, -1);
- }
-
- void resetspawns() { loopv(ents) { extentity *e = ents[i]; e->clearspawned(); e->clearnopickup(); } }
-
- void spawnitems(bool force)
- {
- if(m_noitems) return;
- loopv(ents)
- {
- extentity *e = ents[i];
- if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->type<I_SHELLS || e->type>I_CARTRIDGES))
- {
- e->setspawned(force || !server::delayspawn(e->type));
- e->clearnopickup();
- }
- }
- }
-
- void setspawn(int i, bool on) { if(ents.inrange(i)) { extentity *e = ents[i]; e->setspawned(on); e->clearnopickup(); } }
-
- extentity *newentity() { return new extentity(); }
- void deleteentity(extentity *e) { delete e; }
-
- void clearents()
- {
- while(ents.length()) deleteentity(ents.pop());
- }
-
- void fixentity(extentity &e)
- {
- if(e.type == TELEDEST) e.attr3 = e.attr2;
- }
-
- void entradius(extentity &e, bool color)
- {
- switch(e.type)
- {
- case TELEDEST:
- {
- vec dir;
- vecfromyawpitch(e.attr1, 0, 1, 0, dir);
- renderentarrow(e, dir, 4);
- break;
- }
- case TELEPORT:
- loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2)
- {
- renderentarrow(e, vec(ents[i]->o).sub(e.o).normalize(), e.o.dist(ents[i]->o));
- break;
- }
- break;
-
- case JUMPPAD:
- renderentarrow(e, vec((int)(char)e.attr3*10.0f, (int)(char)e.attr2*10.0f, e.attr1*12.5f).normalize(), 4);
- break;
-
- default: break;
- }
- }
-
- bool printent(extentity &e, char *buf, int len)
- {
- return false;
- }
-
- const char *entnameinfo(entity &e) { return ""; }
- const char *entname(int i)
- {
- static const char * const entnames[] =
- {
- "none?", "light", "mapmodel", "playerstart", "envmap", "particles", "sound", "spotlight",
- "shells", "bullets", "rockets", "riflerounds", "grenades", "cartridges",
- "health", "healthboost", "tinyhealth", "tinyarmour", "greenarmour", "yellowarmour", "quaddamage",
- "teleport", "teledest",
- "jumppad",
- "", "", "", "",
- };
- return i>=0 && size_t(i)<sizeof(entnames)/sizeof(entnames[0]) ? entnames[i] : "";
- }
-
- void editent(int i, bool local)
- {
- extentity &e = *ents[i];
- if(local) addmsg(N_EDITENT, "rii3ii5", i, (int)(e.o.x*DMF), (int)(e.o.y*DMF), (int)(e.o.z*DMF), e.type, e.attr1, e.attr2, e.attr3, e.attr4, e.attr5);
- }
+ d->timeinair = 1;
+ d->vel = v;
+ break;
+ }
+ }
+ }
+
+ void checkitems(fpsent *d)
+ {
+ if(d->state!=CS_ALIVE) return;
+ vec o = d->feetpos();
+ loopv(ents)
+ {
+ extentity &e = *ents[i];
+ if(e.type==NOTUSED) continue;
+ if((!e.spawned() || e.nopickup()) && e.type!=TELEPORT && e.type!=JUMPPAD) continue;
+ float dist = e.o.dist(o);
+ if(dist<(e.type==TELEPORT ? 16 : 12)) trypickup(i, d);
+ }
+ }
+
+ void checkquad(int time, fpsent *d)
+ {
+ if(d->quadmillis && (d->quadmillis -= time)<=0)
+ {
+ d->quadmillis = 0;
+ fpsent *h = followingplayer(player1);
+ playsound(S_PUPOUT, d==h ? NULL : &d->o);
+ if(d==h) conoutf(CON_GAMEINFO, "\f2quad damage is over");
+ }
+ }
+
+ void putitems(packetbuf &p) // puts items in network stream and also spawns them locally
+ {
+ putint(p, N_ITEMLIST);
+ loopv(ents) if(ents[i]->type>=I_SHELLS && ents[i]->type<=I_QUAD && (!m_noammo || ents[i]->type<I_SHELLS || ents[i]->type>I_CARTRIDGES))
+ {
+ putint(p, i);
+ putint(p, ents[i]->type);
+ }
+ putint(p, -1);
+ }
+
+ void resetspawns() { loopv(ents) { extentity *e = ents[i]; e->clearspawned(); e->clearnopickup(); } }
+
+ void spawnitems(bool force)
+ {
+ if(m_noitems) return;
+ loopv(ents)
+ {
+ extentity *e = ents[i];
+ if(e->type>=I_SHELLS && e->type<=I_QUAD && (!m_noammo || e->type<I_SHELLS || e->type>I_CARTRIDGES))
+ {
+ e->setspawned(force || !server::delayspawn(e->type));
+ e->clearnopickup();
+ }
+ }
+ }
+
+ void setspawn(int i, bool on) { if(ents.inrange(i)) { extentity *e = ents[i]; e->setspawned(on); e->clearnopickup(); } }
+
+ extentity *newentity() { return new extentity(); }
+ void deleteentity(extentity *e) { delete e; }
+
+ void clearents()
+ {
+ while(ents.length()) deleteentity(ents.pop());
+ }
+
+ void fixentity(extentity &e)
+ {
+ if(e.type == TELEDEST) e.attr3 = e.attr2;
+ }
+
+ void entradius(extentity &e, bool color)
+ {
+ switch(e.type)
+ {
+ case TELEDEST:
+ {
+ vec dir;
+ vecfromyawpitch(e.attr1, 0, 1, 0, dir);
+ renderentarrow(e, dir, 4);
+ break;
+ }
+ case TELEPORT:
+ loopv(ents) if(ents[i]->type == TELEDEST && e.attr1==ents[i]->attr2)
+ {
+ renderentarrow(e, vec(ents[i]->o).sub(e.o).normalize(), e.o.dist(ents[i]->o));
+ break;
+ }
+ break;
+
+ case JUMPPAD:
+ renderentarrow(e, vec((int)(char)e.attr3*10.0f, (int)(char)e.attr2*10.0f, e.attr1*12.5f).normalize(), 4);
+ break;
+
+ default: break;
+ }
+ }
+
+ bool printent(extentity &e, char *buf, int len)
+ {
+ return false;
+ }
+
+ const char *entnameinfo(entity &e) { return ""; }
+ const char *entname(int i)
+ {
+ static const char * const entnames[] =
+ {
+ "none?", "light", "mapmodel", "playerstart", "envmap", "particles", "sound", "spotlight",
+ "shells", "bullets", "rockets", "riflerounds", "grenades", "cartridges",
+ "health", "healthboost", "tinyhealth", "tinyarmour", "greenarmour", "yellowarmour", "quaddamage",
+ "teleport", "teledest",
+ "jumppad",
+ "", "", "", "",
+ };
+ return i>=0 && size_t(i)<sizeof(entnames)/sizeof(entnames[0]) ? entnames[i] : "";
+ }
+
+ void editent(int i, bool local)
+ {
+ extentity &e = *ents[i];
+ if(local) addmsg(N_EDITENT, "rii3ii5", i, (int)(e.o.x*DMF), (int)(e.o.y*DMF), (int)(e.o.z*DMF), e.type, e.attr1, e.attr2, e.attr3, e.attr4, e.attr5);
+ }
#endif
}