Convert player into a class

FossilOrigin-Name: 5b7b7d2fc5af4d512db195c4fbfb2aff01436db9bc1345d62263609ac129aa02
This commit is contained in:
Jonathan Schleifer 2025-03-24 22:14:24 +00:00
parent 4596a656dc
commit 5835957d74
25 changed files with 211 additions and 166 deletions

View file

@ -3,7 +3,7 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Player.h"
OF_APPLICATION_DELEGATE(Cube)
@ -216,6 +216,8 @@ VARP(minmillis, 0, 5, 1000);
@autoreleasepool {
[OFRunLoop.mainRunLoop runUntilDate:past];
Player *player1 = Player.player1;
int millis = SDL_GetTicks() * gamespeed / 100;
if (millis - lastmillis > 200)
lastmillis = millis - 200;

View file

@ -21,11 +21,8 @@
// bounding box size
@property (nonatomic) float radius, eyeHeight, aboveEye;
@property (nonatomic) int lastUpdate, lag, ping;
// sequence id for each respawn, used in damage test
@property (nonatomic) int lifeSequence;
// one of CS_* below
@property (nonatomic) int state;
@property (nonatomic) int frags;
@property (nonatomic) int health, armour, armourType, quadMillis;
@property (nonatomic) int gunSelect, gunWait;
@property (nonatomic) int lastAction, lastAttackGun, lastMove;
@ -33,7 +30,7 @@
@property (nonatomic) bool attacking;
// used by physics to signal ai
@property (nonatomic) bool blocked, moving;
@property (copy, nonatomic) OFString *name, *team;
@property (copy, nonatomic) OFString *name;
+ (instancetype)entity;
- (OFData *)dataBySerializing;

View file

@ -3,6 +3,7 @@
#include "cube.h"
#import "Monster.h"
#import "Player.h"
struct dynent {
OFVector3D origin, velocity;
@ -58,7 +59,7 @@ struct dynent {
_eyeHeight = 3.2f;
_aboveEye = 0.7f;
_lastUpdate = lastmillis;
_name = _team = @"";
_name = @"";
_state = CS_ALIVE;
[self resetToSpawnState];
@ -98,9 +99,7 @@ struct dynent {
copy->_lastUpdate = _lastUpdate;
copy->_lag = _lag;
copy->_ping = _ping;
copy->_lifeSequence = _lifeSequence;
copy->_state = _state;
copy->_frags = _frags;
copy->_health = _health;
copy->_armour = _armour;
copy->_armourType = _armourType;
@ -118,7 +117,6 @@ struct dynent {
copy->_blocked = _blocked;
copy->_moving = _moving;
copy->_name = [_name copy];
copy->_team = [_team copy];
return copy;
}
@ -150,9 +148,7 @@ struct dynent {
.lastUpdate = _lastUpdate,
.lag = _lag,
.ping = _ping,
.lifeSequence = _lifeSequence,
.state = _state,
.frags = _frags,
.health = _health,
.armour = _armour,
.armourType = _armourType,
@ -166,6 +162,19 @@ struct dynent {
.blocked = _blocked,
.moving = _moving };
for (int i = 0; i < NUMGUNS; i++)
data.ammo[i] = _ammo[i];
memcpy(data.name, _name.UTF8String, min(_name.UTF8StringLength, 259));
if ([self isKindOfClass:Player.class]) {
Player *player = (Player *)self;
data.lifeSequence = player.lifeSequence,
data.frags = player.frags;
memcpy(data.team, player.team.UTF8String,
min(player.team.UTF8StringLength, 259));
}
if ([self isKindOfClass:Monster.class]) {
Monster *monster = (Monster *)self;
data.monsterState = monster.monsterState;
@ -176,12 +185,6 @@ struct dynent {
data.anger = monster.anger;
}
for (int i = 0; i < NUMGUNS; i++)
data.ammo[i] = _ammo[i];
memcpy(data.name, _name.UTF8String, min(_name.UTF8StringLength, 259));
memcpy(data.team, _team.UTF8String, min(_team.UTF8StringLength, 259));
return [OFData dataWithItems:&data count:sizeof(data)];
}
@ -217,9 +220,8 @@ struct dynent {
_lastUpdate = d.lastUpdate;
_lag = d.lag;
_ping = d.ping;
_lifeSequence = d.lifeSequence;
_state = d.state;
_frags = d.frags;
_health = d.health;
_armour = d.armour;
_armourType = d.armourType;
@ -237,6 +239,15 @@ struct dynent {
_blocked = d.blocked;
_moving = d.moving;
_name = [[OFString alloc] initWithUTF8String:d.name];
if ([self isKindOfClass:Player.class]) {
Player *player = (Player *)self;
player.lifeSequence = d.lifeSequence;
player.frags = d.frags;
player.team = @(d.team);
}
if ([self isKindOfClass:Monster.class]) {
Monster *monster = (Monster *)self;
monster.monsterState = d.monsterState;
@ -246,9 +257,6 @@ struct dynent {
monster.attackTarget = d.attackTarget;
monster.anger = d.anger;
}
_name = [[OFString alloc] initWithUTF8String:d.name];
_team = [[OFString alloc] initWithUTF8String:d.team];
}
- (void)resetMovement

View file

@ -4,8 +4,8 @@
#include "cube.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "Player.h"
static OFMutableArray<Monster *> *monsters;
static int nextmonster, spawnremain, numkilled, monstertotal, mtimestart;
@ -101,7 +101,7 @@ monstertypes[NUMMONSTERTYPES] = {
self.trigger = lastmillis + trigger;
self.targetYaw = self.yaw = (float)yaw;
self.move = move;
self.enemy = player1;
self.enemy = Player.player1;
self.gunSelect = t->gun;
self.maxSpeed = (float)t->speed;
self.health = t->health;
@ -256,7 +256,7 @@ enemylos(Monster *m, OFVector3D *v)
- (void)performAction
{
if (self.enemy.state == CS_DEAD) {
self.enemy = player1;
self.enemy = Player.player1;
self.anger = 0;
}
[self normalizeWithAngle:self.targetYaw];
@ -417,7 +417,7 @@ enemylos(Monster *m, OFVector3D *v)
self.state = CS_DEAD;
self.lastAction = lastmillis;
numkilled++;
player1.frags = numkilled;
Player.player1.frags = numkilled;
OFVector3D loc = self.origin;
playsound(monstertypes[self.monsterType].diesound, &loc);
int remain = monstertotal - numkilled;

View file

@ -3,8 +3,8 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Monster.h"
#import "Player.h"
// render players & monsters
// very messy ad-hoc handling of animation frames, should be made more
@ -90,7 +90,7 @@ renderclients()
if (player != [OFNull null] &&
(!demoplayback || i != democlientnum))
renderclient(player,
isteam(player1.team, [player team]),
isteam(Player.player1.team, [player team]),
@"monster/ogro", false, 1.0f);
}];
}
@ -108,8 +108,8 @@ showscores(bool on)
static OFMutableArray<OFString *> *scoreLines;
void
renderscore(DynamicEntity *d)
static void
renderscore(Player *d)
{
OFString *lag = [OFString stringWithFormat:@"%d", d.lag];
OFString *name = [OFString stringWithFormat:@"(%@)", d.name];
@ -131,8 +131,8 @@ static OFString *teamName[maxTeams];
static int teamScore[maxTeams];
static size_t teamsUsed;
void
addteamscore(DynamicEntity *d)
static void
addteamscore(Player *d)
{
for (size_t i = 0; i < teamsUsed; i++) {
if ([teamName[i] isEqual:d.team]) {
@ -155,18 +155,18 @@ renderscores()
return;
[scoreLines removeAllObjects];
if (!demoplayback)
renderscore(player1);
for (id player in players)
if (player != [OFNull null])
renderscore(Player.player1);
for (Player *player in players)
if ([player isKindOfClass:Player.class])
renderscore(player);
sortmenu();
if (m_teammode) {
teamsUsed = 0;
for (id player in players)
if (player != [OFNull null])
for (Player *player in players)
if ([player isKindOfClass:Player.class])
addteamscore(player);
if (!demoplayback)
addteamscore(player1);
addteamscore(Player.player1);
OFMutableString *teamScores = [OFMutableString string];
for (size_t j = 0; j < teamsUsed; j++)
[teamScores appendFormat:@"[ %@: %d ]", teamName[j],

View file

@ -7,6 +7,7 @@
#import "Entity.h"
#import "Monster.h"
#import "OFString+Cube.h"
#import "Player.h"
int nextmode = 0; // nextmode becomes gamemode after next map load
VAR(gamemode, 1, 0, 0);
@ -17,13 +18,11 @@ COMMAND(mode, ARG_1INT, ^(int n) {
bool intermission = false;
DynamicEntity *player1; // our client
OFMutableArray *players; // other clients
void
initPlayers()
{
player1 = [[DynamicEntity alloc] init];
players = [[OFMutableArray alloc] init];
}
@ -44,13 +43,12 @@ getclientmap()
void
respawnself()
{
spawnplayer(player1);
spawnplayer(Player.player1);
showscores(false);
}
static void
arenacount(
DynamicEntity *d, int *alive, int *dead, OFString **lastteam, bool *oneteam)
arenacount(Player *d, int *alive, int *dead, OFString **lastteam, bool *oneteam)
{
if (d.state != CS_DEAD) {
(*alive)++;
@ -82,7 +80,7 @@ arenarespawn()
if (player != [OFNull null])
arenacount(
player, &alive, &dead, &lastteam, &oneteam);
arenacount(player1, &alive, &dead, &lastteam, &oneteam);
arenacount(Player.player1, &alive, &dead, &lastteam, &oneteam);
if (dead > 0 && (alive <= 1 || (m_teammode && oneteam))) {
conoutf(
@"arena round is over! next round in 5 seconds...");
@ -93,7 +91,7 @@ arenarespawn()
conoutf(@"everyone died!");
arenarespawnwait = lastmillis + 5000;
arenadetectwait = lastmillis + 10000;
player1.roll = 0;
Player.player1.roll = 0;
}
}
}
@ -103,28 +101,29 @@ extern int democlientnum;
void
otherplayers()
{
[players enumerateObjectsUsingBlock:^(id player, size_t i, bool *stop) {
if (player == [OFNull null])
return;
[players
enumerateObjectsUsingBlock:^(Player *player, size_t i, bool *stop) {
if ([player isKindOfClass:Player.class])
return;
const int lagtime = lastmillis - [player lastUpdate];
if (lagtime > 1000 && [player state] == CS_ALIVE) {
[player setState:CS_LAGGED];
return;
}
const int lagtime = lastmillis - player.lastUpdate;
if (lagtime > 1000 && player.state == CS_ALIVE) {
player.state = CS_LAGGED;
return;
}
if (lagtime && [player state] != CS_DEAD &&
(!demoplayback || i != democlientnum))
// use physics to extrapolate player position
moveplayer(player, 2, false);
}];
if (lagtime && player.state != CS_DEAD &&
(!demoplayback || i != democlientnum))
// use physics to extrapolate player position
moveplayer(player, 2, false);
}];
}
void
respawn()
{
if (player1.state == CS_DEAD) {
player1.attacking = false;
if (Player.player1.state == CS_DEAD) {
Player.player1.attacking = false;
if (m_arena) {
conoutf(@"waiting for new round to start...");
return;
@ -160,6 +159,7 @@ updateworld(int millis) // main game update loop
arenarespawn();
moveprojectiles((float)curtime);
demoplaybackstep();
Player *player1 = Player.player1;
if (!demoplayback) {
if (getclientnum() >= 0)
// only shoot when connected to server
@ -171,6 +171,7 @@ updateworld(int millis) // main game update loop
otherplayers();
if (!demoplayback) {
[Monster thinkAll];
if (player1.state == CS_DEAD) {
if (lastmillis - player1.lastAction < 2000) {
player1.move = player1.strafe = 0;
@ -182,6 +183,7 @@ updateworld(int millis) // main game update loop
moveplayer(player1, 20, true);
checkitems();
}
// do this last, to reduce the effective frame lag
c2sinfo(player1);
}
@ -213,7 +215,7 @@ int fixspawn = 2;
// place at random spawn. also used by monsters!
void
spawnplayer(DynamicEntity *d)
spawnplayer(Player *d)
{
int r = fixspawn-- > 0 ? 4 : rnd(10) + 1;
for (int i = 0; i < r; i++)
@ -236,6 +238,7 @@ spawnplayer(DynamicEntity *d)
#define dir(name, v, d, s, os) \
COMMAND(name, ARG_DOWN, ^(bool isDown) { \
Player *player1 = Player.player1; \
player1.s = isDown; \
player1.v = isDown ? d : (player1.os ? -(d) : 0); \
player1.lastMove = lastmillis; \
@ -251,12 +254,12 @@ COMMAND(attack, ARG_DOWN, ^(bool on) {
return;
if (editmode)
editdrag(on);
else if ((player1.attacking = on))
else if ((Player.player1.attacking = on))
respawn();
})
COMMAND(jump, ARG_DOWN, ^(bool on) {
if (!intermission && (player1.jumpNext = on))
if (!intermission && (Player.player1.jumpNext = on))
respawn();
})
@ -268,6 +271,7 @@ void
fixplayer1range()
{
const float MAXPITCH = 90.0f;
Player *player1 = Player.player1;
if (player1.pitch > MAXPITCH)
player1.pitch = MAXPITCH;
if (player1.pitch < -MAXPITCH)
@ -281,6 +285,7 @@ fixplayer1range()
void
mousemove(int dx, int dy)
{
Player *player1 = Player.player1;
if (player1.state == CS_DEAD || intermission)
return;
const float SENSF = 33.0f; // try match quake sens
@ -295,14 +300,15 @@ mousemove(int dx, int dy)
void
selfdamage(int damage, int actor, DynamicEntity *act)
{
Player *player1 = Player.player1;
if (player1.state != CS_ALIVE || editmode || intermission)
return;
damageblend(damage);
demoblend(damage);
// let armour absorb when possible
int ad = damage * (player1.armourType + 1) * 20 / 100;
if (ad > player1.armour)
ad = player1.armour;
if (ad > Player.player1.armour)
ad = Player.player1.armour;
player1.armour -= ad;
damage -= ad;
float droll = damage / 0.5f;
@ -321,7 +327,7 @@ selfdamage(int damage, int actor, DynamicEntity *act)
conoutf(@"you suicided!");
addmsg(1, 2, SV_FRAGS, --player1.frags);
} else {
DynamicEntity *a = getclient(actor);
Player *a = getclient(actor);
if (a != nil) {
if (isteam(a.team, player1.team))
conoutf(@"you got fragged by a "
@ -351,7 +357,7 @@ timeupdate(int timeremain)
{
if (!timeremain) {
intermission = true;
player1.attacking = false;
Player.player1.attacking = false;
conoutf(@"intermission:");
conoutf(@"game has ended!");
showscores(true);
@ -360,7 +366,7 @@ timeupdate(int timeremain)
}
}
DynamicEntity *
Player *
getclient(int cn) // ensure valid entity
{
if (cn < 0 || cn >= MAXCLIENTS) {
@ -373,7 +379,7 @@ getclient(int cn) // ensure valid entity
id player = players[cn];
if (player == [OFNull null]) {
player = [DynamicEntity entity];
player = [Player player];
players[cn] = player;
}
@ -408,8 +414,8 @@ startmap(OFString *name) // called just after a map load
[Monster resetAll];
projreset();
spawncycle = -1;
spawnplayer(player1);
player1.frags = 0;
spawnplayer(Player.player1);
Player.player1.frags = 0;
for (id player in players)
if (player != [OFNull null])
[player setFrags:0];

View file

@ -3,7 +3,7 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Player.h"
static ENetHost *clienthost = NULL;
static int connecting = 0;
@ -69,7 +69,7 @@ newname(OFString *name)
if (name.length > 16)
name = [name substringToIndex:16];
player1.name = name;
Player.player1.name = name;
}
COMMAND(name, ARG_1STR, ^(OFString *name) {
@ -84,7 +84,7 @@ newteam(OFString *name)
if (name.length > 5)
name = [name substringToIndex:5];
player1.team = name;
Player.player1.team = name;
}
COMMAND(team, ARG_1STR, ^(OFString *name) {
@ -94,8 +94,8 @@ COMMAND(team, ARG_1STR, ^(OFString *name) {
void
writeclientinfo(OFStream *stream)
{
[stream writeFormat:@"name \"%@\"\nteam \"%@\"\n", player1.name,
player1.team];
[stream writeFormat:@"name \"%@\"\nteam \"%@\"\n", Player.player1.name,
Player.player1.team];
}
void
@ -149,7 +149,7 @@ disconnect(bool onlyclean, bool async)
disconnecting = 0;
clientnum = -1;
c2sinit = false;
player1.lifeSequence = 0;
Player.player1.lifeSequence = 0;
[players removeAllObjects];
localdisconnect();
@ -180,7 +180,7 @@ static OFString *ctext;
void
toserver(OFString *text)
{
conoutf(@"%@:\f %@", player1.name, text);
conoutf(@"%@:\f %@", Player.player1.name, text);
ctext = text;
}
@ -281,7 +281,7 @@ sendpackettoserv(void *packet)
// send update to the server
void
c2sinfo(DynamicEntity *d)
c2sinfo(Player *d)
{
if (clientnum < 0)
return; // we haven't had a welcome message from the server yet
@ -342,9 +342,9 @@ c2sinfo(DynamicEntity *d)
packet->flags = ENET_PACKET_FLAG_RELIABLE;
c2sinit = true;
putint(&p, SV_INITC2S);
sendstring(player1.name, &p);
sendstring(player1.team, &p);
putint(&p, player1.lifeSequence);
sendstring(Player.player1.name, &p);
sendstring(Player.player1.team, &p);
putint(&p, Player.player1.lifeSequence);
}
for (OFData *msg in messages) {
// send messages collected during the previous frames

View file

@ -4,6 +4,7 @@
#import "DynamicEntity.h"
#import "Entity.h"
#import "Player.h"
extern int clientnum;
extern bool c2sinit, senditemstoserver;
@ -37,6 +38,7 @@ changemap(OFString *name) // request map change, server may ignore
void
updatepos(DynamicEntity *d)
{
Player *player1 = Player.player1;
const float r = player1.radius + d.radius;
const float dx = player1.origin.x - d.origin.x;
const float dy = player1.origin.y - d.origin.y;
@ -182,12 +184,13 @@ localservertoclient(unsigned char *buf, int len)
// another client either connected or changed name/team
case SV_INITC2S: {
Player *d_ = (Player *)d;
sgetstr();
if (d.name.length > 0) {
if (d_.name.length > 0) {
// already connected
if (![d.name isEqual:@(text)])
if (![d_.name isEqual:@(text)])
conoutf(@"%@ is now known as %s",
d.name, text);
d_.name, text);
} else {
// new client
@ -195,10 +198,10 @@ localservertoclient(unsigned char *buf, int len)
c2sinit = false;
conoutf(@"connected: %s", text);
}
d.name = @(text);
d_.name = @(text);
sgetstr();
d.team = @(text);
d.lifeSequence = getint(&p);
d_.team = @(text);
d_.lifeSequence = getint(&p);
break;
}
@ -231,7 +234,7 @@ localservertoclient(unsigned char *buf, int len)
int damage = getint(&p);
int ls = getint(&p);
if (target == clientnum) {
if (ls == player1.lifeSequence)
if (ls == Player.player1.lifeSequence)
selfdamage(damage, cn, d);
} else {
OFVector3D loc = getclient(target).origin;
@ -241,23 +244,24 @@ localservertoclient(unsigned char *buf, int len)
}
case SV_DIED: {
Player *d_ = (Player *)d;
int actor = getint(&p);
if (actor == cn) {
conoutf(@"%@ suicided", d.name);
conoutf(@"%@ suicided", d_.name);
} else if (actor == clientnum) {
int frags;
if (isteam(player1.team, d.team)) {
if (isteam(Player.player1.team, d_.team)) {
frags = -1;
conoutf(@"you fragged a teammate (%@)",
d.name);
d_.name);
} else {
frags = 1;
conoutf(@"you fragged %@", d.name);
conoutf(@"you fragged %@", d_.name);
}
addmsg(
1, 2, SV_FRAGS, (player1.frags += frags));
addmsg(1, 2, SV_FRAGS,
(Player.player1.frags += frags));
} else {
DynamicEntity *a = getclient(actor);
Player *a = getclient(actor);
if (a != nil) {
if (isteam(a.team, d.name))
conoutf(@"%@ fragged his "
@ -268,9 +272,9 @@ localservertoclient(unsigned char *buf, int len)
a.name, d.name);
}
}
OFVector3D loc = d.origin;
OFVector3D loc = d_.origin;
playsound(S_DIE1 + rnd(2), &loc);
d.lifeSequence++;
d_.lifeSequence++;
break;
}
@ -295,7 +299,7 @@ localservertoclient(unsigned char *buf, int len)
}
// server acknowledges that I picked up this item
case SV_ITEMACC:
realpickup(getint(&p), player1);
realpickup(getint(&p), Player.player1);
break;
case SV_EDITH: // coop editing messages, should be extended to
@ -361,8 +365,8 @@ localservertoclient(unsigned char *buf, int len)
case SV_PONG:
addmsg(0, 2, SV_CLIENTPING,
player1.ping =
(player1.ping * 5 + lastmillis - getint(&p)) /
Player.player1.ping = (Player.player1.ping * 5 +
lastmillis - getint(&p)) /
6);
break;

View file

@ -8,8 +8,9 @@
#define _MAXDEFSTR 260
@class Entity;
@class DynamicEntity;
@class Entity;
@class Player;
@interface Cube: OFObject <OFApplicationDelegate>
@property (class, readonly, nonatomic) Cube *sharedInstance;
@ -256,8 +257,6 @@ extern struct sqr *world, *wmip[];
extern struct header hdr; // current map header
extern int sfactor, ssize; // ssize = 2^sfactor
extern int cubicsize, mipsize; // cubicsize = ssize^2
// special client ent that receives input and acts as camera
extern DynamicEntity *player1;
// all the other clients (in multiplayer)
extern OFMutableArray *players;
extern bool editmode;

View file

@ -7,6 +7,7 @@
#import "DynamicEntity.h"
#import "Monster.h"
#import "OFString+Cube.h"
#import "Player.h"
bool editmode = false;
@ -58,6 +59,7 @@ VAR(editing, 0, 0, 1);
void
toggleedit()
{
Player *player1 = Player.player1;
if (player1.state == CS_DEAD)
return; // do not allow dead players to edit to avoid state
// confusion
@ -157,6 +159,7 @@ sheight(struct sqr *s, struct sqr *t, float z)
void
cursorupdate() // called every frame from hud
{
Player *player1 = Player.player1;
flrceil = ((int)(player1.pitch >= 0)) * 2;
volatile float x =
@ -626,7 +629,7 @@ COMMAND(newent, ARG_5STR,
^(OFString *what, OFString *a1, OFString *a2, OFString *a3, OFString *a4) {
EDITSEL;
newentity(sel.x, sel.y, (int)player1.origin.z, what,
newentity(sel.x, sel.y, (int)Player.player1.origin.z, what,
[a1 cube_intValueWithBase:0], [a2 cube_intValueWithBase:0],
[a3 cube_intValueWithBase:0], [a4 cube_intValueWithBase:0]);
})

View file

@ -5,6 +5,7 @@
#import "DynamicEntity.h"
#import "Entity.h"
#import "MapModelInfo.h"
#import "Player.h"
OFMutableArray<Entity *> *ents;
@ -128,7 +129,7 @@ struct itemstat {
void
baseammo(int gun)
{
player1.ammo[gun] = itemstats[gun - 1].add * 2;
Player.player1.ammo[gun] = itemstats[gun - 1].add * 2;
}
// these two functions are called when the server acknowledges that you really
@ -147,7 +148,7 @@ radditem(int i, int v)
}
void
realpickup(int n, DynamicEntity *d)
realpickup(int n, Player *d)
{
switch (ents[n].type) {
case I_SHELLS:
@ -294,6 +295,7 @@ pickup(int n, DynamicEntity *d)
lastjumppad = lastmillis;
OFVector3D v = OFMakeVector3D((int)(char)ents[n].attr3 / 10.0f,
(int)(char)ents[n].attr2 / 10.0f, ents[n].attr1 / 10.0f);
Player *player1 = Player.player1;
player1.velocity = OFAddVectors3D(
OFMakeVector3D(player1.velocity.x, player1.velocity.y, 0),
v);
@ -306,6 +308,8 @@ pickup(int n, DynamicEntity *d)
void
checkitems()
{
Player *player1 = Player.player1;
if (editmode)
return;
@ -331,6 +335,8 @@ checkitems()
void
checkquad(int time)
{
Player *player1 = Player.player1;
if (player1.quadMillis && (player1.quadMillis -= time) < 0) {
player1.quadMillis = 0;
playsoundc(S_PUPOUT);

View file

@ -5,8 +5,8 @@
#import "Menu.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "MenuItem.h"
#import "Player.h"
static OFMutableArray<OFNumber *> *menuStack;
static OFMutableArray<Menu *> *menus;
@ -16,7 +16,7 @@ void
menuset(int menu)
{
if ((vmenu = menu) >= 1)
[player1 resetMovement];
[Player.player1 resetMovement];
if (vmenu == 1)
menus[1].menusel = 0;
}

View file

@ -15,6 +15,7 @@ executable('client',
'MenuItem.m',
'Monster.m',
'OFString+Cube.m',
'Player.m',
'Projectile.m',
'ResolverResult.m',
'ResolverThread.m',

View file

@ -10,6 +10,7 @@
#import "Entity.h"
#import "MapModelInfo.h"
#import "Monster.h"
#import "Player.h"
// collide with player or monster
static bool
@ -179,8 +180,8 @@ collide(DynamicEntity *d, bool spawn, float drop, float rise)
return false;
}
if (d != player1)
if (!plcollide(d, player1, &headspace, &hi, &lo))
if (d != Player.player1)
if (!plcollide(d, Player.player1, &headspace, &hi, &lo))
return false;
// this loop can be a performance bottleneck with many monster on a slow

View file

@ -82,7 +82,7 @@ extern bool multiplayer();
extern bool allowedittoggle();
extern void sendpackettoserv(void *packet);
extern void gets2c();
extern void c2sinfo(DynamicEntity *d);
extern void c2sinfo(Player *d);
extern void neterr(OFString *s);
extern void initclientnet();
extern bool netmapstart();
@ -101,7 +101,7 @@ extern void spawnplayer(DynamicEntity *d);
extern void selfdamage(int damage, int actor, DynamicEntity *act);
extern OFString *getclientmap();
extern OFString *modestr(int n);
extern DynamicEntity *getclient(int cn);
extern Player *getclient(int cn);
extern void setclient(int cn, id client);
extern void timeupdate(int timeremain);
extern void fixplayer1range();
@ -255,7 +255,7 @@ extern void renderents();
extern void putitems(unsigned char **p);
extern void checkquad(int time);
extern void checkitems();
extern void realpickup(int n, DynamicEntity *d);
extern void realpickup(int n, Player *d);
extern void renderentities();
extern void resetspawns();
extern void setspawn(size_t i, bool on);

View file

@ -3,8 +3,8 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "Player.h"
void
line(int x1, int y1, float z1, int x2, int y2, float z2)
@ -327,6 +327,8 @@ VARP(crosshairfx, 0, 1, 1);
void
gl_drawhud(int w, int h, int curfps, int nquads, int curvert, bool underwater)
{
Player *player1 = Player.player1;
readmatrices();
if (editmode) {
if (cursordepth == 1.0f)

View file

@ -5,9 +5,9 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Monster.h"
#import "OFString+Cube.h"
#import "Player.h"
#ifdef DARWIN
# define GL_COMBINE_EXT GL_COMBINE_ARB
@ -345,6 +345,8 @@ VARFP(gamma, 30, 100, 300, {
void
transplayer()
{
Player *player1 = Player.player1;
glLoadIdentity();
glRotated(player1.roll, 0.0, 0.0, 1.0);
@ -372,6 +374,8 @@ OFString *hudgunnames[] = { @"hudguns/fist", @"hudguns/shotg",
void
drawhudmodel(int start, int end, float speed, int base)
{
Player *player1 = Player.player1;
rendermodel(hudgunnames[player1.gunSelect], start, end, 0, 1.0f,
OFMakeVector3D(
player1.origin.x, player1.origin.z, player1.origin.y),
@ -381,6 +385,8 @@ drawhudmodel(int start, int end, float speed, int base)
void
drawhudgun(float fovy, float aspect, int farplane)
{
Player *player1 = Player.player1;
if (!hudgun /*|| !player1.gunSelect*/)
return;
@ -410,6 +416,7 @@ drawhudgun(float fovy, float aspect, int farplane)
void
gl_drawframe(int w, int h, float curfps)
{
Player *player1 = Player.player1;
float hf = hdr.waterlevel - 0.3f;
float fovy = (float)fov * h / w;
float aspect = w / (float)h;

View file

@ -3,10 +3,10 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "MD2.h"
#import "MapModelInfo.h"
#import "OFString+Cube.h"
#import "Player.h"
static OFMutableDictionary<OFString *, MD2 *> *mdllookup = nil;
static OFMutableArray<MD2 *> *mapmodels = nil;
@ -90,8 +90,8 @@ rendermodel(OFString *mdl, int frame, int range, int tex, float rad,
{
MD2 *m = loadmodel(mdl);
if (isoccluded(player1.origin.x, player1.origin.y, position.x - rad,
position.z - rad, rad * 2))
if (isoccluded(Player.player1.origin.x, Player.player1.origin.y,
position.x - rad, position.z - rad, rad * 2))
return;
delayedload(m);

View file

@ -2,7 +2,7 @@
#include "cube.h"
#import "DynamicEntity.h"
#import "Player.h"
#define MAXPARTICLES 10500
const int NUMPARTCUTOFF = 20;
@ -56,8 +56,8 @@ void
render_particles(int time)
{
if (demoplayback && demotracking)
newparticle(
player1.origin, OFMakeVector3D(0, 0, 0), 100000000, 8);
newparticle(Player.player1.origin, OFMakeVector3D(0, 0, 0),
100000000, 8);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);

View file

@ -4,9 +4,9 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "Monster.h"
#import "Player.h"
#ifdef OF_BIG_ENDIAN
static const int islittleendian = 0;
@ -18,7 +18,7 @@ static gzFile f = NULL;
bool demorecording = false;
bool demoplayback = false;
bool demoloading = false;
static OFMutableArray<DynamicEntity *> *playerhistory;
static OFMutableArray<Player *> *playerhistory;
int democlientnum = 0;
extern void startdemo();
@ -105,7 +105,7 @@ savestate(OFIRI *IRI)
gzwrite(f, (void *)"CUBESAVE", 8);
gzputc(f, islittleendian);
gzputi(SAVEGAMEVERSION);
OFData *data = [player1 dataBySerializing];
OFData *data = [Player.player1 dataBySerializing];
gzputi(data.count);
char map[_MAXDEFSTR] = { 0 };
memcpy(map, getclientmap().UTF8String,
@ -219,8 +219,8 @@ loadgamerest()
[OFMutableData dataWithCapacity:DynamicEntity.serializedSize];
[data increaseCountBy:DynamicEntity.serializedSize];
gzread(f, data.mutableItems, data.count);
[player1 setFromSerializedData:data];
player1.lastAction = lastmillis;
[Player.player1 setFromSerializedData:data];
Player.player1.lastAction = lastmillis;
int nmonsters = gzgeti();
OFArray<Monster *> *monsters = Monster.monsters;
@ -231,7 +231,7 @@ loadgamerest()
gzread(f, data.mutableItems, data.count);
[monster setFromSerializedData:data];
// lazy, could save id of enemy instead
monster.enemy = player1;
monster.enemy = Player.player1;
// also lazy, but no real noticable effect on game
monster.lastAction = monster.trigger = lastmillis + 500;
if (monster.state == CS_DEAD)
@ -242,7 +242,7 @@ loadgamerest()
int nplayers = gzgeti();
for (int i = 0; i < nplayers; i++) {
if (!gzget()) {
DynamicEntity *d = getclient(i);
Player *d = getclient(i);
assert(d);
gzread(f, data.mutableItems, data.count);
[d setFromSerializedData:data];
@ -300,8 +300,11 @@ demoblend(int damage)
void
incomingdemodata(unsigned char *buf, int len, bool extras)
{
Player *player1 = Player.player1;
if (!demorecording)
return;
gzputi(lastmillis - starttime);
gzputi(len);
gzwrite(f, buf, len);
@ -370,7 +373,7 @@ startdemo()
demoplayback = true;
starttime = lastmillis;
conoutf(@"now playing demo");
setclient(democlientnum, [player1 copy]);
setclient(democlientnum, [Player.player1 copy]);
readdemotime();
}
@ -421,7 +424,7 @@ demoplaybackstep()
gzread(f, buf, len);
localservertoclient(buf, len); // update game state
DynamicEntity *target = players[democlientnum];
Player *target = players[democlientnum];
assert(target);
int extras;
@ -452,7 +455,7 @@ demoplaybackstep()
if (extras &&
(playerhistory.count == 0 ||
playerhistory.lastObject.lastUpdate != playbacktime)) {
DynamicEntity *d = [target copy];
Player *d = [target copy];
d.lastUpdate = playbacktime;
if (playerhistory == nil)
@ -475,13 +478,13 @@ demoplaybackstep()
size_t count = playerhistory.count;
for (ssize_t i = count - 1; i >= 0; i--) {
if (playerhistory[i].lastUpdate < itime) {
DynamicEntity *a = playerhistory[i];
DynamicEntity *b = a;
Player *a = playerhistory[i];
Player *b = a;
if (i + 1 < playerhistory.count)
b = playerhistory[i + 1];
player1 = b;
Player.player1 = b;
// interpolate pos & angles
if (a != b) {
DynamicEntity *c = b;
@ -494,15 +497,15 @@ demoplaybackstep()
// printf("* %d\n", lastmillis);
float bf = (itime - a.lastUpdate) /
(float)(b.lastUpdate - a.lastUpdate);
fixwrap(a, player1);
fixwrap(c, player1);
fixwrap(z, player1);
fixwrap(a, b);
fixwrap(c, b);
fixwrap(z, b);
float dist =
OFDistanceOfVectors3D(c.origin, z.origin);
// if teleport or spawn, don't interpolate
if (dist < 16) {
catmulrom(z.origin, a.origin, b.origin,
c.origin, bf, player1.origin);
c.origin, bf, b.origin);
OFVector3D vz = OFMakeVector3D(
z.yaw, z.pitch, z.roll);
OFVector3D va = OFMakeVector3D(
@ -511,9 +514,8 @@ demoplaybackstep()
b.yaw, b.pitch, b.roll);
OFVector3D vc = OFMakeVector3D(
c.yaw, c.pitch, c.roll);
OFVector3D vp1 =
OFMakeVector3D(player1.yaw,
player1.pitch, player1.roll);
OFVector3D vp1 = OFMakeVector3D(
b.yaw, b.pitch, b.roll);
catmulrom(vz, va, vb, vc, bf, vp1);
z.yaw = vz.x;
z.pitch = vz.y;
@ -527,9 +529,9 @@ demoplaybackstep()
c.yaw = vc.x;
c.pitch = vc.y;
c.roll = vc.z;
player1.yaw = vp1.x;
player1.pitch = vp1.y;
player1.roll = vp1.z;
b.yaw = vp1.x;
b.pitch = vp1.y;
b.roll = vp1.z;
}
fixplayer1range();
}

View file

@ -1,7 +1,7 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Player.h"
#include <SDL_mixer.h>
@ -113,7 +113,7 @@ updatechanvol(int chan, const OFVector3D *loc)
int vol = soundvol, pan = 255 / 2;
if (loc) {
OFVector3D origin = player1.origin;
OFVector3D origin = Player.player1.origin;
float dist = OFDistanceOfVectors3D(origin, *loc);
OFVector3D v = OFSubtractVectors3D(origin, *loc);
@ -122,8 +122,8 @@ updatechanvol(int chan, const OFVector3D *loc)
if (stereo && (v.x != 0 || v.y != 0)) {
// relative angle of sound along X-Y axis
float yaw =
-atan2(v.x, v.y) - player1.yaw * (PI / 180.0f);
float yaw = -atan2(v.x, v.y) -
Player.player1.yaw * (PI / 180.0f);
// range is from 0 (left) to 255 (right)
pan = (int)(255.9f * (0.5 * sin(yaw) + 0.5f));
}

View file

@ -6,6 +6,7 @@
#import "DynamicEntity.h"
#import "Monster.h"
#import "OFString+Cube.h"
#import "Player.h"
#import "Projectile.h"
static const int MONSTERDAMAGEFACTOR = 4;
@ -34,6 +35,8 @@ selectgun(int a, int b, int c)
if (a < -1 || b < -1 || c < -1 || a >= NUMGUNS || b >= NUMGUNS ||
c >= NUMGUNS)
return;
Player *player1 = Player.player1;
int s = player1.gunSelect;
if (a >= 0 && s != a && player1.ammo[a])
s = a;
@ -112,11 +115,11 @@ playerincrosshair()
if (demoplayback)
return NULL;
for (id player in players) {
if (player == [OFNull null])
OFVector3D o = Player.player1.origin;
for (Player *player in players) {
if (![Player isKindOfClass:Player.class])
continue;
OFVector3D o = player1.origin;
if (intersect(player, o, worldpos))
return [player name];
}
@ -162,12 +165,13 @@ static void
hit(int target, int damage, __kindof DynamicEntity *d, DynamicEntity *at)
{
OFVector3D o = d.origin;
if (d == player1)
selfdamage(damage, at == player1 ? -1 : -2, at);
if (d == Player.player1)
selfdamage(damage, (at == Player.player1) ? -1 : -2, at);
else if ([d isKindOfClass:Monster.class])
[d incurDamage:damage fromEntity:at];
else {
addmsg(1, 4, SV_DAMAGE, target, damage, d.lifeSequence);
else if ([d isKindOfClass:Player.class]) {
addmsg(1, 4, SV_DAMAGE, target, damage,
((Player *)d).lifeSequence);
playsound(S_PAIN1 + rnd(5), &o);
}
particle_splash(3, damage, 1000, o);
@ -219,7 +223,7 @@ splash(Projectile *p, OFVector3D v, OFVector3D vold, int notthisplayer,
if (!p.local)
return;
radialeffect(player1, v, -1, qdam, p.owner);
radialeffect(Player.player1, v, -1, qdam, p.owner);
[players enumerateObjectsUsingBlock:^(
id player, size_t i, bool *stop) {
@ -279,8 +283,8 @@ moveprojectiles(float time)
if (player != [OFNull null])
projdamage(player, p, v, i, -1, qdam);
if (p.owner != player1)
projdamage(player1, p, v, -1, -1, qdam);
if (p.owner != Player.player1)
projdamage(Player.player1, p, v, -1, -1, qdam);
for (Monster *monster in Monster.monsters)
if (!vreject(monster.origin, v, 10.0f) &&
@ -310,7 +314,7 @@ void
shootv(int gun, OFVector3D from, OFVector3D to, DynamicEntity *d, bool local)
{
OFVector3D loc = d.origin;
playsound(guns[gun].sound, d == player1 ? NULL : &loc);
playsound(guns[gun].sound, (d == Player.player1) ? NULL : &loc);
int pspeed = 25;
switch (gun) {
case GUN_FIST:
@ -438,5 +442,5 @@ shoot(DynamicEntity *d, OFVector3D targ)
raydamage(monster, from, to, d, -2);
if ([d isKindOfClass:Monster.class])
raydamage(player1, from, to, d, -1);
raydamage(Player.player1, from, to, d, -1);
}

View file

@ -3,9 +3,9 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Entity.h"
#import "Monster.h"
#import "Player.h"
extern OFString *entnames[]; // lookup from map entities above to strings
@ -298,7 +298,7 @@ closestent() // used for delent and edit mode ent display
return;
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
float dist = OFDistanceOfVectors3D(v, player1.origin);
float dist = OFDistanceOfVectors3D(v, Player.player1.origin);
if (dist < bdist) {
best = i;
bdist = dist;
@ -383,7 +383,7 @@ newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4)
case TELEDEST:
e.attr2 = (unsigned char)e.attr1;
case PLAYERSTART:
e.attr1 = (int)player1.yaw;
e.attr1 = (int)Player.player1.yaw;
break;
}
addmsg(1, 10, SV_EDITENT, ents.count, type, e.x, e.y, e.z, e.attr1,

View file

@ -3,7 +3,7 @@
#include "cube.h"
#import "Command.h"
#import "DynamicEntity.h"
#import "Player.h"
#define NUMRAYS 512
@ -21,6 +21,8 @@ COMMAND(toggleocull, ARG_NONE, ^{
void
computeraytable(float vx, float vy)
{
Player *player1 = Player.player1;
if (!ocull)
return;

View file

@ -4,7 +4,7 @@
#include "cube.h"
#import "DynamicEntity.h"
#import "Player.h"
void
render_wall(struct sqr *o, struct sqr *s, int x1, int y1, int x2, int y2,
@ -133,6 +133,7 @@ render_seg_new(
int ry = vyy + lodbot;
float fsize = (float)(1 << mip);
Player *player1 = Player.player1;
for (int ox = x; ox < xs; ox++) {
// first collect occlusion information for this block
for (int oy = y; oy < ys; oy++) {