Convert entity to a class
FossilOrigin-Name: 4b002822f954056510cbb1f85d7687784e26782f63c5995f01ac6488d0632d80
This commit is contained in:
parent
34b31eb77f
commit
d42f82f1ec
19 changed files with 222 additions and 122 deletions
|
@ -94,6 +94,7 @@ VARP(minmillis, 0, 5, 1000);
|
||||||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | par) < 0)
|
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | par) < 0)
|
||||||
fatal(@"Unable to initialize SDL");
|
fatal(@"Unable to initialize SDL");
|
||||||
|
|
||||||
|
initEntities();
|
||||||
initPlayers();
|
initPlayers();
|
||||||
|
|
||||||
log(@"net");
|
log(@"net");
|
||||||
|
|
5
src/Entity.h
Normal file
5
src/Entity.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#import "PersistentEntity.h"
|
||||||
|
|
||||||
|
@interface Entity: PersistentEntity
|
||||||
|
@property (nonatomic) bool spawned; // the only dynamic state of a map entity
|
||||||
|
@end
|
4
src/Entity.m
Normal file
4
src/Entity.m
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
|
@implementation Entity
|
||||||
|
@end
|
11
src/PersistentEntity.h
Normal file
11
src/PersistentEntity.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#import <ObjFW/ObjFW.h>
|
||||||
|
|
||||||
|
// map entity
|
||||||
|
@interface PersistentEntity: OFObject
|
||||||
|
@property (nonatomic) short x, y, z; // cube aligned position
|
||||||
|
@property (nonatomic) short attr1;
|
||||||
|
@property (nonatomic) unsigned char type; // type is one of the above
|
||||||
|
@property (nonatomic) unsigned char attr2, attr3, attr4;
|
||||||
|
|
||||||
|
+ (instancetype)entity;
|
||||||
|
@end
|
8
src/PersistentEntity.m
Normal file
8
src/PersistentEntity.m
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#import "PersistentEntity.h"
|
||||||
|
|
||||||
|
@implementation PersistentEntity
|
||||||
|
+ (instancetype)entity
|
||||||
|
{
|
||||||
|
return [[self alloc] init];
|
||||||
|
}
|
||||||
|
@end
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
#import "OFString+Cube.h"
|
#import "OFString+Cube.h"
|
||||||
|
|
||||||
int nextmode = 0; // nextmode becomes gamemode after next map load
|
int nextmode = 0; // nextmode becomes gamemode after next map load
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
extern int clientnum;
|
extern int clientnum;
|
||||||
extern bool c2sinit, senditemstoserver;
|
extern bool c2sinit, senditemstoserver;
|
||||||
|
@ -280,7 +281,7 @@ localservertoclient(uchar *buf, int len)
|
||||||
case SV_ITEMSPAWN: {
|
case SV_ITEMSPAWN: {
|
||||||
uint i = getint(p);
|
uint i = getint(p);
|
||||||
setspawn(i, true);
|
setspawn(i, true);
|
||||||
if (i >= (uint)ents.length())
|
if (i >= (uint)ents.count)
|
||||||
break;
|
break;
|
||||||
OFVector3D v =
|
OFVector3D v =
|
||||||
OFMakeVector3D(ents[i].x, ents[i].y, ents[i].z);
|
OFMakeVector3D(ents[i].x, ents[i].y, ents[i].z);
|
||||||
|
@ -328,8 +329,13 @@ localservertoclient(uchar *buf, int len)
|
||||||
case SV_EDITENT: // coop edit of ent
|
case SV_EDITENT: // coop edit of ent
|
||||||
{
|
{
|
||||||
uint i = getint(p);
|
uint i = getint(p);
|
||||||
while ((uint)ents.length() <= i)
|
|
||||||
ents.add().type = NOTUSED;
|
while ((uint)ents.count <= i) {
|
||||||
|
Entity *e = [Entity entity];
|
||||||
|
e.type = NOTUSED;
|
||||||
|
[ents addObject:e];
|
||||||
|
}
|
||||||
|
|
||||||
int to = ents[i].type;
|
int to = ents[i].type;
|
||||||
ents[i].type = getint(p);
|
ents[i].type = getint(p);
|
||||||
ents[i].x = getint(p);
|
ents[i].x = getint(p);
|
||||||
|
|
15
src/cube.h
15
src/cube.h
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#define _MAXDEFSTR 260
|
#define _MAXDEFSTR 260
|
||||||
|
|
||||||
|
@class Entity;
|
||||||
@class DynamicEntity;
|
@class DynamicEntity;
|
||||||
|
|
||||||
@interface Cube: OFObject <OFApplicationDelegate>
|
@interface Cube: OFObject <OFApplicationDelegate>
|
||||||
|
@ -76,18 +77,6 @@ enum {
|
||||||
MAXENTTYPES
|
MAXENTTYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
// map entity
|
|
||||||
struct persistent_entity {
|
|
||||||
short x, y, z; // cube aligned position
|
|
||||||
short attr1;
|
|
||||||
uchar type; // type is one of the above
|
|
||||||
uchar attr2, attr3, attr4;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct entity: public persistent_entity {
|
|
||||||
bool spawned; // the only dynamic state of a map entity
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MAPVERSION 5 // bump if map format changes, see worldio.cpp
|
#define MAPVERSION 5 // bump if map format changes, see worldio.cpp
|
||||||
|
|
||||||
// map file format header
|
// map file format header
|
||||||
|
@ -264,7 +253,7 @@ extern DynamicEntity *player1;
|
||||||
// all the other clients (in multiplayer)
|
// all the other clients (in multiplayer)
|
||||||
extern OFMutableArray *players;
|
extern OFMutableArray *players;
|
||||||
extern bool editmode;
|
extern bool editmode;
|
||||||
extern vector<entity> ents; // map entities
|
extern OFMutableArray<Entity *> *ents; // map entities
|
||||||
extern OFVector3D worldpos; // current target of the crosshair in the world
|
extern OFVector3D worldpos; // current target of the crosshair in the world
|
||||||
extern int lastmillis; // last time
|
extern int lastmillis; // last time
|
||||||
extern int curtime; // current frame time
|
extern int curtime; // current frame time
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
#import "MapModelInfo.h"
|
#import "MapModelInfo.h"
|
||||||
|
|
||||||
vector<entity> ents;
|
OFMutableArray<Entity *> *ents;
|
||||||
|
|
||||||
static OFString *entmdlnames[] = {
|
static OFString *entmdlnames[] = {
|
||||||
@"shells",
|
@"shells",
|
||||||
|
@ -23,7 +24,13 @@ static OFString *entmdlnames[] = {
|
||||||
int triggertime = 0;
|
int triggertime = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
renderent(entity &e, OFString *mdlname, float z, float yaw, int frame = 0,
|
initEntities()
|
||||||
|
{
|
||||||
|
ents = [[OFMutableArray alloc] init];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
renderent(Entity *e, OFString *mdlname, float z, float yaw, int frame = 0,
|
||||||
int numf = 1, int basetime = 0, float speed = 10.0f)
|
int numf = 1, int basetime = 0, float speed = 10.0f)
|
||||||
{
|
{
|
||||||
rendermodel(mdlname, frame, numf, 0, 1.1f,
|
rendermodel(mdlname, frame, numf, 0, 1.1f,
|
||||||
|
@ -36,9 +43,8 @@ renderentities()
|
||||||
{
|
{
|
||||||
if (lastmillis > triggertime + 1000)
|
if (lastmillis > triggertime + 1000)
|
||||||
triggertime = 0;
|
triggertime = 0;
|
||||||
loopv(ents)
|
|
||||||
{
|
for (Entity *e in ents) {
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == MAPMODEL) {
|
if (e.type == MAPMODEL) {
|
||||||
MapModelInfo *mmi = getmminfo(e.attr2);
|
MapModelInfo *mmi = getmminfo(e.attr2);
|
||||||
if (mmi == nil)
|
if (mmi == nil)
|
||||||
|
@ -299,21 +305,24 @@ checkitems()
|
||||||
{
|
{
|
||||||
if (editmode)
|
if (editmode)
|
||||||
return;
|
return;
|
||||||
loopv(ents)
|
|
||||||
{
|
[ents enumerateObjectsUsingBlock:^(Entity *e, size_t i, bool *stop) {
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == NOTUSED)
|
if (e.type == NOTUSED)
|
||||||
continue;
|
return;
|
||||||
if (!ents[i].spawned && e.type != TELEPORT && e.type != JUMPPAD)
|
|
||||||
continue;
|
if (!e.spawned && e.type != TELEPORT && e.type != JUMPPAD)
|
||||||
|
return;
|
||||||
|
|
||||||
if (OUTBORD(e.x, e.y))
|
if (OUTBORD(e.x, e.y))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
OFVector3D v = OFMakeVector3D(
|
OFVector3D v = OFMakeVector3D(
|
||||||
e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeheight);
|
e.x, e.y, (float)S(e.x, e.y)->floor + player1.eyeheight);
|
||||||
vdist(dist, t, player1.o, v);
|
vdist(dist, t, player1.o, v);
|
||||||
|
|
||||||
if (dist < (e.type == TELEPORT ? 4 : 2.5))
|
if (dist < (e.type == TELEPORT ? 4 : 2.5))
|
||||||
pickup(i, player1);
|
pickup(i, player1);
|
||||||
}
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -329,22 +338,24 @@ checkquad(int time)
|
||||||
void
|
void
|
||||||
putitems(uchar *&p) // puts items in network stream and also spawns them locally
|
putitems(uchar *&p) // puts items in network stream and also spawns them locally
|
||||||
{
|
{
|
||||||
loopv(ents) if ((ents[i].type >= I_SHELLS && ents[i].type <= I_QUAD) ||
|
[ents enumerateObjectsUsingBlock:^(Entity *e, size_t i, bool *stop) {
|
||||||
ents[i].type == CARROT)
|
if ((e.type >= I_SHELLS && e.type <= I_QUAD) ||
|
||||||
{
|
e.type == CARROT) {
|
||||||
putint(p, i);
|
putint(p, i);
|
||||||
ents[i].spawned = true;
|
e.spawned = true;
|
||||||
}
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
resetspawns()
|
resetspawns()
|
||||||
{
|
{
|
||||||
loopv(ents) ents[i].spawned = false;
|
for (Entity *e in ents)
|
||||||
|
e.spawned = false;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
setspawn(uint i, bool on)
|
setspawn(uint i, bool on)
|
||||||
{
|
{
|
||||||
if (i < (uint)ents.length())
|
if (i < (uint)ents.count)
|
||||||
ents[i].spawned = on;
|
ents[i].spawned = on;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ executable('client',
|
||||||
'ConsoleLine.m',
|
'ConsoleLine.m',
|
||||||
'Cube.mm',
|
'Cube.mm',
|
||||||
'DynamicEntity.mm',
|
'DynamicEntity.mm',
|
||||||
|
'Entity.m',
|
||||||
'Identifier.m',
|
'Identifier.m',
|
||||||
'KeyMapping.m',
|
'KeyMapping.m',
|
||||||
'MD2.mm',
|
'MD2.mm',
|
||||||
|
@ -13,6 +14,7 @@ executable('client',
|
||||||
'Menu.m',
|
'Menu.m',
|
||||||
'MenuItem.m',
|
'MenuItem.m',
|
||||||
'OFString+Cube.mm',
|
'OFString+Cube.mm',
|
||||||
|
'PersistentEntity.m',
|
||||||
'Projectile.m',
|
'Projectile.m',
|
||||||
'ResolverResult.mm',
|
'ResolverResult.mm',
|
||||||
'ResolverThread.mm',
|
'ResolverThread.mm',
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
static OFMutableArray<DynamicEntity *> *monsters;
|
static OFMutableArray<DynamicEntity *> *monsters;
|
||||||
static int nextmonster, spawnremain, numkilled, monstertotal, mtimestart;
|
static int nextmonster, spawnremain, numkilled, monstertotal, mtimestart;
|
||||||
|
@ -121,11 +122,14 @@ monsterclear()
|
||||||
monstertotal = spawnremain = gamemode < 0 ? skill * 10 : 0;
|
monstertotal = spawnremain = gamemode < 0 ? skill * 10 : 0;
|
||||||
} else if (m_classicsp) {
|
} else if (m_classicsp) {
|
||||||
mtimestart = lastmillis;
|
mtimestart = lastmillis;
|
||||||
loopv(ents) if (ents[i].type == MONSTER)
|
|
||||||
{
|
for (Entity *e in ents) {
|
||||||
DynamicEntity *m = basicmonster(
|
if (e.type != MONSTER)
|
||||||
ents[i].attr2, ents[i].attr1, M_SLEEP, 100, 0);
|
continue;
|
||||||
m.o = OFMakeVector3D(ents[i].x, ents[i].y, ents[i].z);
|
|
||||||
|
DynamicEntity *m =
|
||||||
|
basicmonster(e.attr2, e.attr1, M_SLEEP, 100, 0);
|
||||||
|
m.o = OFMakeVector3D(e.x, e.y, e.z);
|
||||||
entinmap(m);
|
entinmap(m);
|
||||||
monstertotal++;
|
monstertotal++;
|
||||||
}
|
}
|
||||||
|
@ -377,13 +381,13 @@ monsterthink()
|
||||||
endsp(true);
|
endsp(true);
|
||||||
|
|
||||||
// equivalent of player entity touch, but only teleports are used
|
// equivalent of player entity touch, but only teleports are used
|
||||||
loopv(ents)
|
[ents enumerateObjectsUsingBlock:^(Entity *e, size_t i, bool *stop) {
|
||||||
{
|
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type != TELEPORT)
|
if (e.type != TELEPORT)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
if (OUTBORD(e.x, e.y))
|
if (OUTBORD(e.x, e.y))
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
OFVector3D v =
|
OFVector3D v =
|
||||||
OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor);
|
OFMakeVector3D(e.x, e.y, (float)S(e.x, e.y)->floor);
|
||||||
for (DynamicEntity *monster in monsters) {
|
for (DynamicEntity *monster in monsters) {
|
||||||
|
@ -396,11 +400,12 @@ monsterthink()
|
||||||
v.z += monster.eyeheight;
|
v.z += monster.eyeheight;
|
||||||
vdist(dist, t, monster.o, v);
|
vdist(dist, t, monster.o, v);
|
||||||
v.z -= monster.eyeheight;
|
v.z -= monster.eyeheight;
|
||||||
|
|
||||||
if (dist < 4)
|
if (dist < 4)
|
||||||
teleport((int)(&e - &ents[0]), monster);
|
teleport(i, monster);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}];
|
||||||
|
|
||||||
for (DynamicEntity *monster in monsters)
|
for (DynamicEntity *monster in monsters)
|
||||||
if (monster.state == CS_ALIVE)
|
if (monster.state == CS_ALIVE)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
#import "MapModelInfo.h"
|
#import "MapModelInfo.h"
|
||||||
|
|
||||||
// collide with player or monster
|
// collide with player or monster
|
||||||
|
@ -58,18 +59,19 @@ cornertest(int mip, int x, int y, int dx, int dy, int &bx, int &by,
|
||||||
void
|
void
|
||||||
mmcollide(DynamicEntity *d, float &hi, float &lo) // collide with a mapmodel
|
mmcollide(DynamicEntity *d, float &hi, float &lo) // collide with a mapmodel
|
||||||
{
|
{
|
||||||
loopv(ents)
|
for (Entity *e in ents) {
|
||||||
{
|
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type != MAPMODEL)
|
if (e.type != MAPMODEL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MapModelInfo *mmi = getmminfo(e.attr2);
|
MapModelInfo *mmi = getmminfo(e.attr2);
|
||||||
if (mmi == nil || !mmi.h)
|
if (mmi == nil || !mmi.h)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const float r = mmi.rad + d.radius;
|
const float r = mmi.rad + d.radius;
|
||||||
if (fabs(e.x - d.o.x) < r && fabs(e.y - d.o.y) < r) {
|
if (fabs(e.x - d.o.x) < r && fabs(e.y - d.o.y) < r) {
|
||||||
float mmz =
|
float mmz =
|
||||||
(float)(S(e.x, e.y)->floor + mmi.zoff + e.attr3);
|
(float)(S(e.x, e.y)->floor + mmi.zoff + e.attr3);
|
||||||
|
|
||||||
if (d.o.z - d.eyeheight < mmz) {
|
if (d.o.z - d.eyeheight < mmz) {
|
||||||
if (mmz < hi)
|
if (mmz < hi)
|
||||||
hi = mmz;
|
hi = mmz;
|
||||||
|
|
|
@ -121,7 +121,7 @@ extern int findentity(int type, int index = 0);
|
||||||
extern void trigger(int tag, int type, bool savegame);
|
extern void trigger(int tag, int type, bool savegame);
|
||||||
extern void resettagareas();
|
extern void resettagareas();
|
||||||
extern void settagareas();
|
extern void settagareas();
|
||||||
extern entity *newentity(
|
extern Entity *newentity(
|
||||||
int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4);
|
int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4);
|
||||||
|
|
||||||
// worldlight
|
// worldlight
|
||||||
|
@ -227,7 +227,7 @@ extern void putint(uchar *&p, int n);
|
||||||
extern int getint(uchar *&p);
|
extern int getint(uchar *&p);
|
||||||
extern void sendstring(OFString *t, uchar *&p);
|
extern void sendstring(OFString *t, uchar *&p);
|
||||||
extern void startintermission();
|
extern void startintermission();
|
||||||
extern void restoreserverstate(vector<entity> &ents);
|
extern void restoreserverstate(OFArray<Entity *> *ents);
|
||||||
extern uchar *retrieveservers(uchar *buf, int buflen);
|
extern uchar *retrieveservers(uchar *buf, int buflen);
|
||||||
extern char msgsizelookup(int msg);
|
extern char msgsizelookup(int msg);
|
||||||
extern void serverms(int mode, int numplayers, int minremain,
|
extern void serverms(int mode, int numplayers, int minremain,
|
||||||
|
@ -257,6 +257,7 @@ extern void monsterpain(DynamicEntity *m, int damage, DynamicEntity *d);
|
||||||
extern void endsp(bool allkilled);
|
extern void endsp(bool allkilled);
|
||||||
|
|
||||||
// entities
|
// entities
|
||||||
|
extern void initEntities();
|
||||||
extern void renderents();
|
extern void renderents();
|
||||||
extern void putitems(uchar *&p);
|
extern void putitems(uchar *&p);
|
||||||
extern void checkquad(int time);
|
extern void checkquad(int time);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
line(int x1, int y1, float z1, int x2, int y2, float z2)
|
line(int x1, int y1, float z1, int x2, int y2, float z2)
|
||||||
|
@ -175,23 +176,26 @@ OFString *entnames[] = {
|
||||||
@"?",
|
@"?",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// show sparkly thingies for map entities in edit mode
|
||||||
void
|
void
|
||||||
renderents() // show sparkly thingies for map entities in edit mode
|
renderents()
|
||||||
{
|
{
|
||||||
closeent = @"";
|
closeent = @"";
|
||||||
|
|
||||||
if (!editmode)
|
if (!editmode)
|
||||||
return;
|
return;
|
||||||
loopv(ents)
|
|
||||||
{
|
for (Entity *e in ents) {
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == NOTUSED)
|
if (e.type == NOTUSED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
|
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
|
||||||
particle_splash(2, 2, 40, v);
|
particle_splash(2, 2, 40, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
int e = closestent();
|
int e = closestent();
|
||||||
if (e >= 0) {
|
if (e >= 0) {
|
||||||
entity &c = ents[e];
|
Entity *c = ents[e];
|
||||||
closeent =
|
closeent =
|
||||||
[OFString stringWithFormat:@"closest entity = %@ (%d, %d, "
|
[OFString stringWithFormat:@"closest entity = %@ (%d, %d, "
|
||||||
@"%d, %d), selection = (%d, %d)",
|
@"%d, %d), selection = (%d, %d)",
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
#ifdef OF_BIG_ENDIAN
|
#ifdef OF_BIG_ENDIAN
|
||||||
static const int islittleendian = 0;
|
static const int islittleendian = 0;
|
||||||
|
@ -109,8 +110,9 @@ savestate(OFIRI *IRI)
|
||||||
min(getclientmap().UTF8StringLength, _MAXDEFSTR - 1));
|
min(getclientmap().UTF8StringLength, _MAXDEFSTR - 1));
|
||||||
gzwrite(f, map, _MAXDEFSTR);
|
gzwrite(f, map, _MAXDEFSTR);
|
||||||
gzputi(gamemode);
|
gzputi(gamemode);
|
||||||
gzputi(ents.length());
|
gzputi(ents.count);
|
||||||
loopv(ents) gzputc(f, ents[i].spawned);
|
for (Entity *e in ents)
|
||||||
|
gzputc(f, e.spawned);
|
||||||
gzwrite(f, data.items, data.count);
|
gzwrite(f, data.items, data.count);
|
||||||
OFArray<DynamicEntity *> *monsters = getmonsters();
|
OFArray<DynamicEntity *> *monsters = getmonsters();
|
||||||
gzputi(monsters.count);
|
gzputi(monsters.count);
|
||||||
|
@ -205,14 +207,16 @@ loadgamerest()
|
||||||
if (demoplayback || !f)
|
if (demoplayback || !f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (gzgeti() != ents.length())
|
if (gzgeti() != ents.count)
|
||||||
return loadgameout();
|
return loadgameout();
|
||||||
loopv(ents)
|
|
||||||
{
|
for (Entity *e in ents) {
|
||||||
ents[i].spawned = gzgetc(f) != 0;
|
e.spawned = (gzgetc(f) != 0);
|
||||||
if (ents[i].type == CARROT && !ents[i].spawned)
|
|
||||||
trigger(ents[i].attr1, ents[i].attr2, true);
|
if (e.type == CARROT && !e.spawned)
|
||||||
|
trigger(e.attr1, e.attr2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
restoreserverstate(ents);
|
restoreserverstate(ents);
|
||||||
|
|
||||||
OFMutableData *data =
|
OFMutableData *data =
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "Client.h"
|
#import "Client.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };
|
enum { ST_EMPTY, ST_LOCAL, ST_TCPIP };
|
||||||
|
|
||||||
|
@ -24,9 +25,9 @@ vector<server_entity> sents;
|
||||||
bool notgotitems = true;
|
bool notgotitems = true;
|
||||||
int mode = 0;
|
int mode = 0;
|
||||||
|
|
||||||
|
// hack: called from savegame code, only works in SP
|
||||||
void
|
void
|
||||||
restoreserverstate(
|
restoreserverstate(OFArray<Entity *> *ents)
|
||||||
vector<entity> &ents) // hack: called from savegame code, only works in SP
|
|
||||||
{
|
{
|
||||||
loopv(sents)
|
loopv(sents)
|
||||||
{
|
{
|
||||||
|
|
87
src/world.mm
87
src/world.mm
|
@ -3,6 +3,7 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
extern OFString *entnames[]; // lookup from map entities above to strings
|
extern OFString *entnames[]; // lookup from map entities above to strings
|
||||||
|
|
||||||
|
@ -53,7 +54,11 @@ void
|
||||||
settagareas()
|
settagareas()
|
||||||
{
|
{
|
||||||
settag(0, 1);
|
settag(0, 1);
|
||||||
loopv(ents) if (ents[i].type == CARROT) setspawn(i, true);
|
|
||||||
|
[ents enumerateObjectsUsingBlock:^(Entity *e, size_t i, bool *stop) {
|
||||||
|
if (ents[i].type == CARROT)
|
||||||
|
setspawn(i, true);
|
||||||
|
}];
|
||||||
} // set for playing
|
} // set for playing
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -256,21 +261,22 @@ closestent() // used for delent and edit mode ent display
|
||||||
{
|
{
|
||||||
if (noteditmode())
|
if (noteditmode())
|
||||||
return -1;
|
return -1;
|
||||||
int best;
|
|
||||||
float bdist = 99999;
|
__block int best;
|
||||||
loopv(ents)
|
__block float bdist = 99999;
|
||||||
{
|
[ents enumerateObjectsUsingBlock:^(Entity *e, size_t i, bool *stop) {
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == NOTUSED)
|
if (e.type == NOTUSED)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
|
OFVector3D v = OFMakeVector3D(e.x, e.y, e.z);
|
||||||
vdist(dist, t, player1.o, v);
|
vdist(dist, t, player1.o, v);
|
||||||
if (dist < bdist) {
|
if (dist < bdist) {
|
||||||
best = i;
|
best = i;
|
||||||
bdist = dist;
|
bdist = dist;
|
||||||
}
|
}
|
||||||
}
|
}];
|
||||||
return bdist == 99999 ? -1 : best;
|
|
||||||
|
return (bdist == 99999 ? -1 : best);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -319,12 +325,21 @@ findtype(OFString *what)
|
||||||
return NOTUSED;
|
return NOTUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity *
|
Entity *
|
||||||
newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4)
|
newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4)
|
||||||
{
|
{
|
||||||
int type = findtype(what);
|
int type = findtype(what);
|
||||||
persistent_entity e = { (short)x, (short)y, (short)z, (short)v1,
|
|
||||||
(uchar)type, (uchar)v2, (uchar)v3, (uchar)v4 };
|
PersistentEntity *e = [PersistentEntity entity];
|
||||||
|
e.x = x;
|
||||||
|
e.y = y;
|
||||||
|
e.z = z;
|
||||||
|
e.attr1 = v1;
|
||||||
|
e.type = type;
|
||||||
|
e.attr2 = v2;
|
||||||
|
e.attr3 = v3;
|
||||||
|
e.attr4 = v4;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LIGHT:
|
case LIGHT:
|
||||||
if (v1 > 32)
|
if (v1 > 32)
|
||||||
|
@ -345,59 +360,63 @@ newentity(int x, int y, int z, OFString *what, int v1, int v2, int v3, int v4)
|
||||||
e.attr1 = (int)player1.yaw;
|
e.attr1 = (int)player1.yaw;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
addmsg(1, 10, SV_EDITENT, ents.length(), type, e.x, e.y, e.z, e.attr1,
|
addmsg(1, 10, SV_EDITENT, ents.count, type, e.x, e.y, e.z, e.attr1,
|
||||||
e.attr2, e.attr3, e.attr4);
|
e.attr2, e.attr3, e.attr4);
|
||||||
ents.add(*((entity *)&e)); // unsafe!
|
|
||||||
|
[ents addObject:e]; // unsafe!
|
||||||
|
|
||||||
if (type == LIGHT)
|
if (type == LIGHT)
|
||||||
calclight();
|
calclight();
|
||||||
return &ents.last();
|
|
||||||
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clearents(OFString *name)
|
clearents(OFString *name)
|
||||||
{
|
{
|
||||||
int type = findtype(name);
|
int type = findtype(name);
|
||||||
|
|
||||||
if (noteditmode() || multiplayer())
|
if (noteditmode() || multiplayer())
|
||||||
return;
|
return;
|
||||||
loopv(ents)
|
|
||||||
{
|
for (Entity *e in ents)
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == type)
|
if (e.type == type)
|
||||||
e.type = NOTUSED;
|
e.type = NOTUSED;
|
||||||
}
|
|
||||||
if (type == LIGHT)
|
if (type == LIGHT)
|
||||||
calclight();
|
calclight();
|
||||||
}
|
}
|
||||||
COMMAND(clearents, ARG_1STR)
|
COMMAND(clearents, ARG_1STR)
|
||||||
|
|
||||||
void
|
static uchar
|
||||||
scalecomp(uchar &c, int intens)
|
scalecomp(uchar c, int intens)
|
||||||
{
|
{
|
||||||
int n = c * intens / 100;
|
int n = c * intens / 100;
|
||||||
if (n > 255)
|
if (n > 255)
|
||||||
n = 255;
|
n = 255;
|
||||||
c = n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scalelights(int f, int intens)
|
scalelights(int f, int intens)
|
||||||
{
|
{
|
||||||
loopv(ents)
|
for (Entity *e in ents) {
|
||||||
{
|
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type != LIGHT)
|
if (e.type != LIGHT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
e.attr1 = e.attr1 * f / 100;
|
e.attr1 = e.attr1 * f / 100;
|
||||||
if (e.attr1 < 2)
|
if (e.attr1 < 2)
|
||||||
e.attr1 = 2;
|
e.attr1 = 2;
|
||||||
if (e.attr1 > 32)
|
if (e.attr1 > 32)
|
||||||
e.attr1 = 32;
|
e.attr1 = 32;
|
||||||
|
|
||||||
if (intens) {
|
if (intens) {
|
||||||
scalecomp(e.attr2, intens);
|
e.attr2 = scalecomp(e.attr2, intens);
|
||||||
scalecomp(e.attr3, intens);
|
e.attr3 = scalecomp(e.attr3, intens);
|
||||||
scalecomp(e.attr4, intens);
|
e.attr4 = scalecomp(e.attr4, intens);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
calclight();
|
calclight();
|
||||||
}
|
}
|
||||||
COMMAND(scalelights, ARG_2INT)
|
COMMAND(scalelights, ARG_2INT)
|
||||||
|
@ -405,7 +424,7 @@ COMMAND(scalelights, ARG_2INT)
|
||||||
int
|
int
|
||||||
findentity(int type, int index)
|
findentity(int type, int index)
|
||||||
{
|
{
|
||||||
for (int i = index; i < ents.length(); i++)
|
for (int i = index; i < ents.count; i++)
|
||||||
if (ents[i].type == type)
|
if (ents[i].type == type)
|
||||||
return i;
|
return i;
|
||||||
loopj(index) if (ents[j].type == type) return j;
|
loopj(index) if (ents[j].type == type) return j;
|
||||||
|
@ -474,10 +493,10 @@ empty_world(int factor, bool force)
|
||||||
*S(x + ssize / 4, y + ssize / 4) =
|
*S(x + ssize / 4, y + ssize / 4) =
|
||||||
*SWS(oldworld, x, y, ssize / 2);
|
*SWS(oldworld, x, y, ssize / 2);
|
||||||
}
|
}
|
||||||
loopv(ents)
|
|
||||||
{
|
for (Entity *e in ents) {
|
||||||
ents[i].x += ssize / 4;
|
e.x += ssize / 4;
|
||||||
ents[i].y += ssize / 4;
|
e.y += ssize / 4;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char buffer[128] = "Untitled Map by Unknown";
|
char buffer[128] = "Untitled Map by Unknown";
|
||||||
|
@ -485,7 +504,7 @@ empty_world(int factor, bool force)
|
||||||
hdr.waterlevel = -100000;
|
hdr.waterlevel = -100000;
|
||||||
loopi(15) hdr.reserved[i] = 0;
|
loopi(15) hdr.reserved[i] = 0;
|
||||||
loopk(3) loopi(256) hdr.texlists[k][i] = i;
|
loopk(3) loopi(256) hdr.texlists[k][i] = i;
|
||||||
ents.setsize(0);
|
[ents removeAllObjects];
|
||||||
block b = { 8, 8, ssize - 16, ssize - 16 };
|
block b = { 8, 8, ssize - 16, ssize - 16 };
|
||||||
edittypexy(SPACE, b);
|
edittypexy(SPACE, b);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,15 @@
|
||||||
|
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
|
#import "Entity.h"
|
||||||
|
|
||||||
|
struct persistent_entity {
|
||||||
|
short x, y, z; // cube aligned position
|
||||||
|
short attr1;
|
||||||
|
uchar type; // type is one of the above
|
||||||
|
uchar attr2, attr3, attr4;
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
backup(OFString *name, OFString *backupname)
|
backup(OFString *name, OFString *backupname)
|
||||||
{
|
{
|
||||||
|
@ -173,15 +182,17 @@ save_world(OFString *mname)
|
||||||
}
|
}
|
||||||
hdr.version = MAPVERSION;
|
hdr.version = MAPVERSION;
|
||||||
hdr.numents = 0;
|
hdr.numents = 0;
|
||||||
loopv(ents) if (ents[i].type != NOTUSED) hdr.numents++;
|
for (Entity *e in ents)
|
||||||
|
if (e.type != NOTUSED)
|
||||||
|
hdr.numents++;
|
||||||
header tmp = hdr;
|
header tmp = hdr;
|
||||||
endianswap(&tmp.version, sizeof(int), 4);
|
endianswap(&tmp.version, sizeof(int), 4);
|
||||||
endianswap(&tmp.waterlevel, sizeof(int), 16);
|
endianswap(&tmp.waterlevel, sizeof(int), 16);
|
||||||
gzwrite(f, &tmp, sizeof(header));
|
gzwrite(f, &tmp, sizeof(header));
|
||||||
loopv(ents)
|
for (Entity *e in ents) {
|
||||||
{
|
if (e.type != NOTUSED) {
|
||||||
if (ents[i].type != NOTUSED) {
|
struct persistent_entity tmp = { e.x, e.y, e.z, e.attr1,
|
||||||
entity tmp = ents[i];
|
e.type, e.attr2, e.attr3, e.attr4 };
|
||||||
endianswap(&tmp, sizeof(short), 4);
|
endianswap(&tmp, sizeof(short), 4);
|
||||||
gzwrite(f, &tmp, sizeof(persistent_entity));
|
gzwrite(f, &tmp, sizeof(persistent_entity));
|
||||||
}
|
}
|
||||||
|
@ -273,13 +284,24 @@ load_world(OFString *mname) // still supports all map formats that have existed
|
||||||
} else {
|
} else {
|
||||||
hdr.waterlevel = -100000;
|
hdr.waterlevel = -100000;
|
||||||
}
|
}
|
||||||
ents.setsize(0);
|
[ents removeAllObjects];
|
||||||
loopi(hdr.numents)
|
loopi(hdr.numents)
|
||||||
{
|
{
|
||||||
entity &e = ents.add();
|
struct persistent_entity tmp;
|
||||||
gzread(f, &e, sizeof(persistent_entity));
|
gzread(f, &tmp, sizeof(persistent_entity));
|
||||||
endianswap(&e, sizeof(short), 4);
|
endianswap(&tmp, sizeof(short), 4);
|
||||||
e.spawned = false;
|
|
||||||
|
Entity *e = [Entity entity];
|
||||||
|
e.x = tmp.x;
|
||||||
|
e.y = tmp.y;
|
||||||
|
e.z = tmp.z;
|
||||||
|
e.attr1 = tmp.attr1;
|
||||||
|
e.type = tmp.type;
|
||||||
|
e.attr2 = tmp.attr2;
|
||||||
|
e.attr3 = tmp.attr3;
|
||||||
|
e.attr4 = tmp.attr4;
|
||||||
|
[ents addObject:e];
|
||||||
|
|
||||||
if (e.type == LIGHT) {
|
if (e.type == LIGHT) {
|
||||||
if (!e.attr2)
|
if (!e.attr2)
|
||||||
e.attr2 = 255; // needed for MAPVERSION<=2
|
e.attr2 = 255; // needed for MAPVERSION<=2
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
#include "cube.h"
|
#include "cube.h"
|
||||||
|
|
||||||
#import "DynamicEntity.h"
|
#import "DynamicEntity.h"
|
||||||
|
#import "Entity.h"
|
||||||
|
#import "PersistentEntity.h"
|
||||||
|
|
||||||
extern bool hasoverbright;
|
extern bool hasoverbright;
|
||||||
|
|
||||||
VAR(lightscale, 1, 4, 100);
|
VAR(lightscale, 1, 4, 100);
|
||||||
|
|
||||||
|
// done in realtime, needs to be fast
|
||||||
void
|
void
|
||||||
lightray(float bx, float by,
|
lightray(float bx, float by, PersistentEntity *light)
|
||||||
persistent_entity &light) // done in realtime, needs to be fast
|
|
||||||
{
|
{
|
||||||
float lx = light.x + (rnd(21) - 10) * 0.1f;
|
float lx = light.x + (rnd(21) - 10) * 0.1f;
|
||||||
float ly = light.y + (rnd(21) - 10) * 0.1f;
|
float ly = light.y + (rnd(21) - 10) * 0.1f;
|
||||||
|
@ -121,7 +123,7 @@ lightray(float bx, float by,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
calclightsource(persistent_entity &l)
|
calclightsource(PersistentEntity *l)
|
||||||
{
|
{
|
||||||
int reach = l.attr1;
|
int reach = l.attr1;
|
||||||
int sx = l.x - reach;
|
int sx = l.x - reach;
|
||||||
|
@ -175,12 +177,9 @@ calclight()
|
||||||
s->r = s->g = s->b = 10;
|
s->r = s->g = s->b = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
loopv(ents)
|
for (Entity *e in ents)
|
||||||
{
|
|
||||||
entity &e = ents[i];
|
|
||||||
if (e.type == LIGHT)
|
if (e.type == LIGHT)
|
||||||
calclightsource(e);
|
calclightsource(e);
|
||||||
}
|
|
||||||
|
|
||||||
block b = { 1, 1, ssize - 2, ssize - 2 };
|
block b = { 1, 1, ssize - 2, ssize - 2 };
|
||||||
postlightarea(b);
|
postlightarea(b);
|
||||||
|
@ -236,8 +235,13 @@ dodynlight(const OFVector3D &vold, const OFVector3D &v, int reach, int strength,
|
||||||
block *copy = blockcopy(b);
|
block *copy = blockcopy(b);
|
||||||
[dlights addItem:©];
|
[dlights addItem:©];
|
||||||
|
|
||||||
persistent_entity l = { (short)v.x, (short)v.y, (short)v.z,
|
PersistentEntity *l = [Entity entity];
|
||||||
(short)reach, LIGHT, (uchar)strength, 0, 0 };
|
l.x = v.x;
|
||||||
|
l.y = v.y;
|
||||||
|
l.z = v.z;
|
||||||
|
l.attr1 = reach;
|
||||||
|
l.type = LIGHT;
|
||||||
|
l.attr2 = strength;
|
||||||
calclightsource(l);
|
calclightsource(l);
|
||||||
postlightarea(b);
|
postlightarea(b);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue