Migrate projectile to a class

FossilOrigin-Name: d3b4b2d476d809f7ab00502eed47614c949264690b3eccc7a96c73687d0f05bf
This commit is contained in:
Jonathan Schleifer 2025-03-09 11:24:01 +00:00
parent dae9d5553c
commit 410e244ed6
9 changed files with 97 additions and 82 deletions

11
src/Projectile.h Normal file
View file

@ -0,0 +1,11 @@
#import <ObjFW/ObjFW.h>
typedef struct dynent dynent;
@interface Projectile: OFObject
@property (nonatomic) OFVector3D o, to;
@property (nonatomic) float speed;
@property (nonatomic) dynent *owner;
@property (nonatomic) int gun;
@property (nonatomic) bool inuse, local;
@end

4
src/Projectile.m Normal file
View file

@ -0,0 +1,4 @@
#import "Projectile.h"
@implementation Projectile
@end

View file

@ -9,6 +9,7 @@ executable('client',
'MapModelInfo.m', 'MapModelInfo.m',
'Menu.m', 'Menu.m',
'MenuItem.m', 'MenuItem.m',
'Projectile.m',
'Variable.mm', 'Variable.mm',
'client.mm', 'client.mm',
'clientextras.mm', 'clientextras.mm',

View file

@ -125,8 +125,8 @@ extern entity *newentity(
// worldlight // worldlight
extern void calclight(); extern void calclight();
extern void dodynlight( extern void dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach,
OFVector3D &vold, OFVector3D &v, int reach, int strength, dynent *owner); int strength, dynent *owner);
extern void cleardlights(); extern void cleardlights();
extern block *blockcopy(block &b); extern block *blockcopy(block &b);
extern void blockpaste(block &b); extern void blockpaste(block &b);
@ -166,7 +166,7 @@ extern void line(int x1, int y1, float z1, int x2, int y2, float z2);
extern void box(block &b, float z1, float z2, float z3, float z4); extern void box(block &b, float z1, float z2, float z3, float z4);
extern void dot(int x, int y, float z); extern void dot(int x, int y, float z);
extern void linestyle(float width, int r, int g, int b); extern void linestyle(float width, int r, int g, int b);
extern void newsphere(OFVector3D &o, float max, int type); extern void newsphere(const OFVector3D &o, float max, int type);
extern void renderspheres(int time); extern void renderspheres(int time);
extern void gl_drawhud( extern void gl_drawhud(
int w, int h, int curfps, int nquads, int curvert, bool underwater); int w, int h, int curfps, int nquads, int curvert, bool underwater);
@ -176,7 +176,7 @@ extern void damageblend(int n);
// renderparticles // renderparticles
extern void setorient(OFVector3D &r, OFVector3D &u); extern void setorient(OFVector3D &r, OFVector3D &u);
extern void particle_splash(int type, int num, int fade, OFVector3D &p); extern void particle_splash(int type, int num, int fade, const OFVector3D &p);
extern void particle_trail( extern void particle_trail(
int type, int fade, OFVector3D &from, OFVector3D &to); int type, int fade, OFVector3D &from, OFVector3D &to);
extern void render_particles(int time); extern void render_particles(int time);
@ -202,7 +202,7 @@ extern void setentphysics(int mml, int mmr);
extern void physicsframe(); extern void physicsframe();
// sound // sound
extern void playsound(int n, OFVector3D *loc = 0); extern void playsound(int n, const OFVector3D *loc = NULL);
extern void playsoundc(int n); extern void playsoundc(int n);
extern void initsound(); extern void initsound();
extern void cleansound(); extern void cleansound();

View file

@ -89,7 +89,7 @@ sphere spheres[MAXSPHERES], *slist = NULL, *sempty = NULL;
bool sinit = false; bool sinit = false;
void void
newsphere(OFVector3D &o, float max, int type) newsphere(const OFVector3D &o, float max, int type)
{ {
if (!sinit) { if (!sinit) {
loopi(MAXSPHERES) loopi(MAXSPHERES)

View file

@ -15,8 +15,8 @@ bool parinit = false;
VARP(maxparticles, 100, 2000, MAXPARTICLES - 500); VARP(maxparticles, 100, 2000, MAXPARTICLES - 500);
void static void
newparticle(OFVector3D &o, OFVector3D &d, int fade, int type) newparticle(const OFVector3D &o, const OFVector3D &d, int fade, int type)
{ {
if (!parinit) { if (!parinit) {
loopi(MAXPARTICLES) loopi(MAXPARTICLES)
@ -133,7 +133,7 @@ render_particles(int time)
} }
void void
particle_splash(int type, int num, int fade, OFVector3D &p) particle_splash(int type, int num, int fade, const OFVector3D &p)
{ {
loopi(num) loopi(num)
{ {
@ -144,8 +144,7 @@ particle_splash(int type, int num, int fade, OFVector3D &p)
y = rnd(radius * 2) - radius; y = rnd(radius * 2) - radius;
z = rnd(radius * 2) - radius; z = rnd(radius * 2) - radius;
} while (x * x + y * y + z * z > radius * radius); } while (x * x + y * y + z * z > radius * radius);
OFVector3D d = OFMakeVector3D(x, y, z); newparticle(p, OFMakeVector3D(x, y, z), rnd(fade * 3), type);
newparticle(p, d, rnd(fade * 3), type);
} }
} }

View file

@ -92,14 +92,16 @@ music(OFString *name)
IRIByAppendingPathComponent:path]; IRIByAppendingPathComponent:path];
#ifdef USE_MIXER #ifdef USE_MIXER
if (mod = Mix_LoadMUS( if ((mod = Mix_LoadMUS(
IRI.fileSystemRepresentation.UTF8String)) { IRI.fileSystemRepresentation.UTF8String)) !=
NULL) {
Mix_PlayMusic(mod, -1); Mix_PlayMusic(mod, -1);
Mix_VolumeMusic((musicvol * MAXVOL) / 255); Mix_VolumeMusic((musicvol * MAXVOL) / 255);
} }
#else #else
if (mod = FMUSIC_LoadSong( if ((mod = FMUSIC_LoadSong(
IRI.fileSystemRepresentation.UTF8String)) { IRI.fileSystemRepresentation.UTF8String)) !=
NULL) {
FMUSIC_PlaySong(mod); FMUSIC_PlaySong(mod);
FMUSIC_SetMasterVolume(mod, musicvol); FMUSIC_SetMasterVolume(mod, musicvol);
} else if (stream = FSOUND_Stream_Open( } else if (stream = FSOUND_Stream_Open(
@ -166,8 +168,8 @@ cleansound()
VAR(stereo, 0, 1, 1); VAR(stereo, 0, 1, 1);
void static void
updatechanvol(int chan, OFVector3D *loc) updatechanvol(int chan, const OFVector3D *loc)
{ {
int vol = soundvol, pan = 255 / 2; int vol = soundvol, pan = 255 / 2;
if (loc) { if (loc) {
@ -194,8 +196,8 @@ updatechanvol(int chan, OFVector3D *loc)
#endif #endif
} }
void static void
newsoundloc(int chan, OFVector3D *loc) newsoundloc(int chan, const OFVector3D *loc)
{ {
assert(chan >= 0 && chan < MAXCHAN); assert(chan >= 0 && chan < MAXCHAN);
soundlocs[chan].loc = *loc; soundlocs[chan].loc = *loc;
@ -230,7 +232,7 @@ playsoundc(int n)
int soundsatonce = 0, lastsoundmillis = 0; int soundsatonce = 0, lastsoundmillis = 0;
void void
playsound(int n, OFVector3D *loc) playsound(int n, const OFVector3D *loc)
{ {
if (nosound) if (nosound)
return; return;

View file

@ -2,17 +2,17 @@
#include "cube.h" #include "cube.h"
struct guninfo { #import "Projectile.h"
short sound, attackdelay, damage, projspeed, part, kickamount;
OFString *name;
};
static const int MONSTERDAMAGEFACTOR = 4; static const int MONSTERDAMAGEFACTOR = 4;
static const int SGRAYS = 20; static const int SGRAYS = 20;
static const float SGSPREAD = 2; static const float SGSPREAD = 2;
static OFVector3D sg[SGRAYS]; static OFVector3D sg[SGRAYS];
static const guninfo guns[NUMGUNS] = { static const struct {
short sound, attackdelay, damage, projspeed, part, kickamount;
OFString *name;
} guns[NUMGUNS] = {
{ S_PUNCH1, 250, 50, 0, 0, 1, @"fist" }, { S_PUNCH1, 250, 50, 0, 0, 1, @"fist" },
{ S_SG, 1400, 10, 0, 0, 20, @"shotgun" }, // *SGRAYS { S_SG, 1400, 10, 0, 0, 20, @"shotgun" }, // *SGRAYS
{ S_CG, 100, 30, 0, 0, 7, @"chaingun" }, { S_CG, 100, 30, 0, 0, 7, @"chaingun" },
@ -83,11 +83,12 @@ createrays(OFVector3D &from,
} }
} }
// if lineseg hits entity bounding box
bool bool
intersect(dynent *d, OFVector3D &from, intersect(dynent *d, const OFVector3D &from, const OFVector3D &to)
OFVector3D &to) // if lineseg hits entity bounding box
{ {
OFVector3D v = to, w = d->o, *p; OFVector3D v = to, w = d->o;
const OFVector3D *p;
vsub(v, from); vsub(v, from);
vsub(w, from); vsub(w, from);
float c1 = dotprod(w, v); float c1 = dotprod(w, v);
@ -128,37 +129,33 @@ playerincrosshair()
return nil; return nil;
} }
const int MAXPROJ = 100; static const size_t MAXPROJ = 100;
struct projectile { static Projectile *projs[MAXPROJ];
OFVector3D o, to;
float speed;
dynent *owner;
int gun;
bool inuse, local;
} projs[MAXPROJ];
void void
projreset() projreset()
{ {
loopi(MAXPROJ) projs[i].inuse = false; for (size_t i = 0; i < MAXPROJ; i++)
projs[i].inuse = false;
} }
void void
newprojectile(OFVector3D &from, OFVector3D &to, float speed, bool local, newprojectile(OFVector3D &from, OFVector3D &to, float speed, bool local,
dynent *owner, int gun) dynent *owner, int gun)
{ {
loopi(MAXPROJ) for (size_t i = 0; i < MAXPROJ; i++) {
{ Projectile *p = projs[i];
projectile *p = &projs[i];
if (p->inuse) if (p.inuse)
continue; continue;
p->inuse = true;
p->o = from; p.inuse = true;
p->to = to; p.o = from;
p->speed = speed; p.to = to;
p->local = local; p.speed = speed;
p->owner = owner; p.local = local;
p->gun = gun; p.owner = owner;
p.gun = gun;
return; return;
} }
} }
@ -181,8 +178,8 @@ hit(int target, int damage, dynent *d, dynent *at)
const float RL_RADIUS = 5; const float RL_RADIUS = 5;
const float RL_DAMRAD = 7; // hack const float RL_DAMRAD = 7; // hack
void static void
radialeffect(dynent *o, OFVector3D &v, int cn, int qdam, dynent *at) radialeffect(dynent *o, const OFVector3D &v, int cn, int qdam, dynent *at)
{ {
if (o->state != CS_ALIVE) if (o->state != CS_ALIVE)
return; return;
@ -199,21 +196,21 @@ radialeffect(dynent *o, OFVector3D &v, int cn, int qdam, dynent *at)
} }
void void
splash(projectile *p, OFVector3D &v, OFVector3D &vold, int notthisplayer, splash(Projectile *p, const OFVector3D &v, const OFVector3D &vold,
int notthismonster, int qdam) int notthisplayer, int notthismonster, int qdam)
{ {
particle_splash(0, 50, 300, v); particle_splash(0, 50, 300, v);
p->inuse = false; p.inuse = false;
if (p->gun != GUN_RL) { if (p.gun != GUN_RL) {
playsound(S_FEXPLODE, &v); playsound(S_FEXPLODE, &v);
// no push? // no push?
} else { } else {
playsound(S_RLHIT, &v); playsound(S_RLHIT, &v);
newsphere(v, RL_RADIUS, 0); newsphere(v, RL_RADIUS, 0);
dodynlight(vold, v, 0, 0, p->owner); dodynlight(vold, v, 0, 0, p.owner);
if (!p->local) if (!p.local)
return; return;
radialeffect(player1, v, -1, qdam, p->owner); radialeffect(player1, v, -1, qdam, p.owner);
loopv(players) loopv(players)
{ {
if (i == notthisplayer) if (i == notthisplayer)
@ -221,42 +218,43 @@ splash(projectile *p, OFVector3D &v, OFVector3D &vold, int notthisplayer,
dynent *o = players[i]; dynent *o = players[i];
if (!o) if (!o)
continue; continue;
radialeffect(o, v, i, qdam, p->owner); radialeffect(o, v, i, qdam, p.owner);
} }
dvector &mv = getmonsters(); dvector &mv = getmonsters();
loopv(mv) if (i != notthismonster) loopv(mv) if (i != notthismonster)
radialeffect(mv[i], v, i, qdam, p->owner); radialeffect(mv[i], v, i, qdam, p.owner);
} }
} }
inline void inline void
projdamage(dynent *o, projectile *p, OFVector3D &v, int i, int im, int qdam) projdamage(dynent *o, Projectile *p, OFVector3D &v, int i, int im, int qdam)
{ {
if (o->state != CS_ALIVE) if (o->state != CS_ALIVE)
return; return;
if (intersect(o, p->o, v)) { if (intersect(o, p.o, v)) {
splash(p, v, p->o, i, im, qdam); splash(p, v, p.o, i, im, qdam);
hit(i, qdam, o, p->owner); hit(i, qdam, o, p.owner);
} }
} }
void void
moveprojectiles(float time) moveprojectiles(float time)
{ {
loopi(MAXPROJ) for (size_t i = 0; i < MAXPROJ; i++) {
{ Projectile *p = projs[i];
projectile *p = &projs[i];
if (!p->inuse) if (!p.inuse)
continue; continue;
int qdam = guns[p->gun].damage * (p->owner->quadmillis ? 4 : 1);
if (p->owner->monsterstate) int qdam = guns[p.gun].damage * (p.owner->quadmillis ? 4 : 1);
if (p.owner->monsterstate)
qdam /= MONSTERDAMAGEFACTOR; qdam /= MONSTERDAMAGEFACTOR;
vdist(dist, v, p->o, p->to); vdist(dist, v, p.o, p.to);
float dtime = dist * 1000 / p->speed; float dtime = dist * 1000 / p.speed;
if (time > dtime) if (time > dtime)
dtime = time; dtime = time;
vmul(v, time / dtime); vmul(v, time / dtime);
vadd(v, p->o) if (p->local) vadd(v, p.o) if (p.local)
{ {
loopv(players) loopv(players)
{ {
@ -265,28 +263,28 @@ moveprojectiles(float time)
continue; continue;
projdamage(o, p, v, i, -1, qdam); projdamage(o, p, v, i, -1, qdam);
} }
if (p->owner != player1) if (p.owner != player1)
projdamage(player1, p, v, -1, -1, qdam); projdamage(player1, p, v, -1, -1, qdam);
dvector &mv = getmonsters(); dvector &mv = getmonsters();
loopv(mv) if (!vreject(mv[i]->o, v, 10.0f) && loopv(mv) if (!vreject(mv[i]->o, v, 10.0f) &&
mv[i] != p->owner) mv[i] != p.owner)
projdamage(mv[i], p, v, -1, i, qdam); projdamage(mv[i], p, v, -1, i, qdam);
} }
if (p->inuse) { if (p.inuse) {
if (time == dtime) if (time == dtime)
splash(p, v, p->o, -1, -1, qdam); splash(p, v, p.o, -1, -1, qdam);
else { else {
if (p->gun == GUN_RL) { if (p.gun == GUN_RL) {
dodynlight(p->o, v, 0, 255, p->owner); dodynlight(p.o, v, 0, 255, p.owner);
particle_splash(5, 2, 200, v); particle_splash(5, 2, 200, v);
} else { } else {
particle_splash(1, 1, 200, v); particle_splash(1, 1, 200, v);
particle_splash( particle_splash(
guns[p->gun].part, 1, 1, v); guns[p.gun].part, 1, 1, v);
} }
} }
} }
p->o = v; p.o = v;
} }
} }

View file

@ -200,8 +200,8 @@ cleardlights()
} }
void void
dodynlight( dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach, int strength,
OFVector3D &vold, OFVector3D &v, int reach, int strength, dynent *owner) dynent *owner)
{ {
if (!reach) if (!reach)
reach = dynlight; reach = dynlight;