FossilOrigin-Name: 5b7b7d2fc5af4d512db195c4fbfb2aff01436db9bc1345d62263609ac129aa02
335 lines
6.8 KiB
Objective-C
335 lines
6.8 KiB
Objective-C
#import "DynamicEntity.h"
|
|
|
|
#include "cube.h"
|
|
|
|
#import "Monster.h"
|
|
#import "Player.h"
|
|
|
|
struct dynent {
|
|
OFVector3D origin, velocity;
|
|
float yaw, pitch, roll;
|
|
float maxSpeed;
|
|
bool outsideMap;
|
|
bool inWater;
|
|
bool onFloor, jumpNext;
|
|
int move, strafe;
|
|
bool k_left, k_right, k_up, k_down;
|
|
int timeInAir;
|
|
float radius, eyeHeight, aboveEye;
|
|
int lastUpdate, lag, ping;
|
|
int lifeSequence;
|
|
int state;
|
|
int frags;
|
|
int health, armour, armourType, quadMillis;
|
|
int gunSelect, gunWait;
|
|
int lastAction, lastAttackGun, lastMove;
|
|
bool attacking;
|
|
int ammo[NUMGUNS];
|
|
int monsterState;
|
|
int monsterType;
|
|
void *enemy;
|
|
float targetYaw;
|
|
bool blocked, moving;
|
|
int trigger;
|
|
OFVector3D attackTarget;
|
|
int anger;
|
|
char name[260], team[260];
|
|
};
|
|
|
|
@implementation DynamicEntity
|
|
+ (instancetype)entity
|
|
{
|
|
return [[self alloc] init];
|
|
}
|
|
|
|
+ (size_t)serializedSize
|
|
{
|
|
return sizeof(struct dynent);
|
|
}
|
|
|
|
- (instancetype)init
|
|
{
|
|
self = [super init];
|
|
|
|
_ammo = (int *)OFAllocZeroedMemory(NUMGUNS, sizeof(int));
|
|
|
|
_yaw = 270;
|
|
_maxSpeed = 22;
|
|
_radius = 1.1f;
|
|
_eyeHeight = 3.2f;
|
|
_aboveEye = 0.7f;
|
|
_lastUpdate = lastmillis;
|
|
_name = @"";
|
|
_state = CS_ALIVE;
|
|
|
|
[self resetToSpawnState];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
OFFreeMemory(_ammo);
|
|
}
|
|
|
|
- (id)copy
|
|
{
|
|
DynamicEntity *copy = [[self.class alloc] init];
|
|
|
|
copy->_origin = _origin;
|
|
copy->_velocity = _velocity;
|
|
copy->_yaw = _yaw;
|
|
copy->_pitch = _pitch;
|
|
copy->_roll = _roll;
|
|
copy->_maxSpeed = _maxSpeed;
|
|
copy->_outsideMap = _outsideMap;
|
|
copy->_inWater = _inWater;
|
|
copy->_onFloor = _onFloor;
|
|
copy->_jumpNext = _jumpNext;
|
|
copy->_move = _move;
|
|
copy->_strafe = _strafe;
|
|
copy->_k_left = _k_left;
|
|
copy->_k_right = _k_right;
|
|
copy->_k_up = _k_up;
|
|
copy->_k_down = _k_down;
|
|
copy->_timeInAir = _timeInAir;
|
|
copy->_radius = _radius;
|
|
copy->_eyeHeight = _eyeHeight;
|
|
copy->_aboveEye = _aboveEye;
|
|
copy->_lastUpdate = _lastUpdate;
|
|
copy->_lag = _lag;
|
|
copy->_ping = _ping;
|
|
copy->_state = _state;
|
|
copy->_health = _health;
|
|
copy->_armour = _armour;
|
|
copy->_armourType = _armourType;
|
|
copy->_quadMillis = _quadMillis;
|
|
copy->_gunSelect = _gunSelect;
|
|
copy->_gunWait = _gunWait;
|
|
copy->_lastAction = _lastAction;
|
|
copy->_lastAttackGun = _lastAttackGun;
|
|
copy->_lastMove = _lastMove;
|
|
copy->_attacking = _attacking;
|
|
|
|
for (size_t i = 0; i < NUMGUNS; i++)
|
|
copy->_ammo[i] = _ammo[i];
|
|
|
|
copy->_blocked = _blocked;
|
|
copy->_moving = _moving;
|
|
copy->_name = [_name copy];
|
|
|
|
return copy;
|
|
}
|
|
|
|
- (OFData *)dataBySerializing
|
|
{
|
|
// This is frighteningly *TERRIBLE*, but the format used by existing
|
|
// savegames.
|
|
struct dynent data = { .origin = _origin,
|
|
.velocity = _velocity,
|
|
.yaw = _yaw,
|
|
.pitch = _pitch,
|
|
.roll = _roll,
|
|
.maxSpeed = _maxSpeed,
|
|
.outsideMap = _outsideMap,
|
|
.inWater = _inWater,
|
|
.onFloor = _onFloor,
|
|
.jumpNext = _jumpNext,
|
|
.move = _move,
|
|
.strafe = _strafe,
|
|
.k_left = _k_left,
|
|
.k_right = _k_right,
|
|
.k_up = _k_up,
|
|
.k_down = _k_down,
|
|
.timeInAir = _timeInAir,
|
|
.radius = _radius,
|
|
.eyeHeight = _eyeHeight,
|
|
.aboveEye = _aboveEye,
|
|
.lastUpdate = _lastUpdate,
|
|
.lag = _lag,
|
|
.ping = _ping,
|
|
.state = _state,
|
|
.health = _health,
|
|
.armour = _armour,
|
|
.armourType = _armourType,
|
|
.quadMillis = _quadMillis,
|
|
.gunSelect = _gunSelect,
|
|
.gunWait = _gunWait,
|
|
.lastAction = _lastAction,
|
|
.lastAttackGun = _lastAttackGun,
|
|
.lastMove = _lastMove,
|
|
.attacking = _attacking,
|
|
.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;
|
|
data.monsterType = monster.monsterType;
|
|
data.targetYaw = monster.targetYaw;
|
|
data.trigger = monster.trigger;
|
|
data.attackTarget = monster.attackTarget;
|
|
data.anger = monster.anger;
|
|
}
|
|
|
|
return [OFData dataWithItems:&data count:sizeof(data)];
|
|
}
|
|
|
|
- (void)setFromSerializedData:(OFData *)data
|
|
{
|
|
struct dynent d;
|
|
|
|
if (data.count != sizeof(struct dynent))
|
|
@throw [OFOutOfRangeException exception];
|
|
|
|
memcpy(&d, data.items, data.count);
|
|
|
|
_origin = d.origin;
|
|
_velocity = d.velocity;
|
|
_yaw = d.yaw;
|
|
_pitch = d.pitch;
|
|
_roll = d.roll;
|
|
_maxSpeed = d.maxSpeed;
|
|
_outsideMap = d.outsideMap;
|
|
_inWater = d.inWater;
|
|
_onFloor = d.onFloor;
|
|
_jumpNext = d.jumpNext;
|
|
_move = d.move;
|
|
_strafe = d.strafe;
|
|
_k_left = d.k_left;
|
|
_k_right = d.k_right;
|
|
_k_up = d.k_up;
|
|
_k_down = d.k_down;
|
|
_timeInAir = d.timeInAir;
|
|
_radius = d.radius;
|
|
_eyeHeight = d.eyeHeight;
|
|
_aboveEye = d.aboveEye;
|
|
_lastUpdate = d.lastUpdate;
|
|
_lag = d.lag;
|
|
_ping = d.ping;
|
|
_state = d.state;
|
|
|
|
_health = d.health;
|
|
_armour = d.armour;
|
|
_armourType = d.armourType;
|
|
_quadMillis = d.quadMillis;
|
|
_gunSelect = d.gunSelect;
|
|
_gunWait = d.gunWait;
|
|
_lastAction = d.lastAction;
|
|
_lastAttackGun = d.lastAttackGun;
|
|
_lastMove = d.lastMove;
|
|
_attacking = d.attacking;
|
|
|
|
for (int i = 0; i < NUMGUNS; i++)
|
|
_ammo[i] = d.ammo[i];
|
|
|
|
_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;
|
|
monster.monsterType = d.monsterType;
|
|
monster.targetYaw = d.targetYaw;
|
|
monster.trigger = d.trigger;
|
|
monster.attackTarget = d.attackTarget;
|
|
monster.anger = d.anger;
|
|
}
|
|
}
|
|
|
|
- (void)resetMovement
|
|
{
|
|
_k_left = false;
|
|
_k_right = false;
|
|
_k_up = false;
|
|
_k_down = false;
|
|
_jumpNext = false;
|
|
_strafe = 0;
|
|
_move = 0;
|
|
}
|
|
|
|
- (void)resetToSpawnState
|
|
{
|
|
[self resetMovement];
|
|
|
|
_velocity = OFMakeVector3D(0, 0, 0);
|
|
_onFloor = false;
|
|
_timeInAir = 0;
|
|
_health = 100;
|
|
_armour = 50;
|
|
_armourType = A_BLUE;
|
|
_quadMillis = 0;
|
|
_lastAttackGun = _gunSelect = GUN_SG;
|
|
_gunWait = 0;
|
|
_attacking = false;
|
|
_lastAction = 0;
|
|
|
|
for (size_t i = 0; i < NUMGUNS; i++)
|
|
_ammo[i] = 0;
|
|
_ammo[GUN_FIST] = 1;
|
|
|
|
if (m_noitems) {
|
|
_gunSelect = GUN_RIFLE;
|
|
_armour = 0;
|
|
|
|
if (m_noitemsrail) {
|
|
_health = 1;
|
|
_ammo[GUN_RIFLE] = 100;
|
|
} else {
|
|
if (gamemode == 12) {
|
|
// eihrul's secret "instafist" mode
|
|
_gunSelect = GUN_FIST;
|
|
return;
|
|
}
|
|
|
|
_health = 256;
|
|
|
|
if (m_tarena) {
|
|
_gunSelect = rnd(4) + 1;
|
|
baseammo(_gunSelect);
|
|
|
|
int gun2;
|
|
do {
|
|
gun2 = rnd(4) + 1;
|
|
} while (gun2 != _gunSelect);
|
|
|
|
baseammo(gun2);
|
|
} else if (m_arena) {
|
|
// insta arena
|
|
_ammo[GUN_RIFLE] = 100;
|
|
} else {
|
|
// efficiency
|
|
for (size_t i = 0; i < 4; i++)
|
|
baseammo(i + 1);
|
|
|
|
_gunSelect = GUN_CG;
|
|
}
|
|
|
|
_ammo[GUN_CG] /= 2;
|
|
}
|
|
} else
|
|
_ammo[GUN_SG] = 5;
|
|
}
|
|
@end
|