/*
Copyright (C) 2015-2018 Night Dive Studios, LLC.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef __OBJAPP_H
#define __OBJAPP_H
/*
** $Header: r:/prj/cit/src/inc/RCS/objapp.h 1.25 1994/08/30 07:15:21 xemu Exp $
*
*/
//////////////////////////////
//
// An ObjClass is an enum encompassing all the different classes
// in the world. Be sure to set NUM_CLASSES and CLASS_FIRST
// correctly.
//
// An ObjRefState specifies the location of an ObjRef.
//
// It is made up of two parts:
//
// - ObjRefStateBin is used to choose where to put an ObjRef
// in the world-wide data structure. All ObjRefs with the
// same ObjRefStateBin are part of the same chain.
//
// - ObjRefStateInfo is extra information associated with an
// ObjRef's location. For example, in Freefall we specify
// here what rendering triangles an object overlaps. If
// you have no such information in your application, then
// #define NO_OBJ_REF_STATE_INFO.
//
// There must be a specific ObjRefStateBin which is "null".
// For example, it is used to terminate lists of ObjRefStateBins.
// The ObjRefStateBinSetNull and -CheckNull macros respectively
// set a bin to be null and check if it is null.
//
// An ObjLoc specifies the location of an Obj.
// An ObjInfo contains any extra information that you need to have associated
// with each and every object.
//
// #define HASH_OBJECTS if you want ObjRef chains to be hashed
// by location. You must then define the number of entries, and
// how many of those entries are accessible by the hashing function.
// (I recommend keeping these in the ratio 2:1). You must also write
// a macro (or function if you prefer) that computes a number n such that
// OBJ_HASH_HEAD_ENTRIES_START <= n < OBJ_HASH_ENTRIES, given an
// ObjRefStateBin.
//
// If you do not #define HASH_OBJECTS, you must write a macro that provides
// the head of the ObjRef chain for a given bin. (You are responsible for
// keeping a 2-dimensional array of bins, or whatever.) This must be a macro
// so that the object system can take the address of the result.
////////////////////////////// HERE IS THE STUFF YOU MUST CHANGE
// //
// ////////////////////////////////
//#include
// #define HASH_OBJECTS
#define NO_OBJ_REF_STATE_INFO
// enumeration of classes
// ## INSERT NEW CLASS HERE
typedef enum ObjClass {
CLASS_GUN,
CLASS_AMMO,
CLASS_PHYSICS,
CLASS_GRENADE,
CLASS_DRUG,
CLASS_HARDWARE,
CLASS_SOFTWARE,
CLASS_BIGSTUFF,
CLASS_SMALLSTUFF,
CLASS_FIXTURE,
CLASS_DOOR,
CLASS_ANIMATING,
CLASS_TRAP,
CLASS_CONTAINER,
CLASS_CRITTER,
NUM_CLASSES,
CLASS_FIRST = CLASS_GUN
} ObjClass;
// The total number of objects in the game, and of each type
// ## INSERT NEW CLASS HERE
//
#define NUM_OBJECTS 872
#define NUM_OBJECTS_GUN 16
#define NUM_OBJECTS_AMMO 32
#define NUM_OBJECTS_PHYSICS 32
#define NUM_OBJECTS_GRENADE 32
#define NUM_OBJECTS_DRUG 32
#define NUM_OBJECTS_HARDWARE 8
#define NUM_OBJECTS_SOFTWARE 16
#define NUM_OBJECTS_BIGSTUFF 176
#define NUM_OBJECTS_SMALLSTUFF 128
#define NUM_OBJECTS_FIXTURE 64
#define NUM_OBJECTS_DOOR 64
#define NUM_OBJECTS_ANIMATING 32
#define NUM_OBJECTS_TRAP 160
#define NUM_OBJECTS_CONTAINER 64
#define NUM_OBJECTS_CRITTER 64
// THe total number of references of objects
#define NUM_REF_OBJECTS 1600
// i hate cpp, no sizeof() in #if, so we have to do this
#define SIZEOF_AN_OBJREFSTATEBIN 4
typedef struct {
LGPoint sq;
} ObjRefStateBin;
#define OBJREF_SQ(ori) (objRefs[ori].state.bin.sq)
// i hate cpp, no sizeof() in #if, so we have to do this
#define SIZEOF_AN_OBJREFSTATEINFO 1
typedef struct {
uchar flags;
} ObjRefStateInfo;
#define ObjRefStateBinSetNull(bin) PointSetNull((bin).sq)
#define ObjRefStateBinCheckNull(bin) (PointCheckNull((bin).sq))
// i hate cpp, no sizeof() in #if, so we have to do this
#define SIZEOF_AN_OBJLOC 8
typedef struct {
ushort x, y; // high 8 bits: what square low 8 bits: where within square
ubyte z;
ubyte p, h, b;
} ObjLoc;
#define OBJ_LOC_BIN_X(oloc) ((oloc).x >> 8)
#define OBJ_LOC_BIN_Y(oloc) ((oloc).y >> 8)
#define OBJ_LOC_FINE_X(oloc) ((ushort)((oloc).x & 0xFF))
#define OBJ_LOC_FINE_Y(oloc) ((ushort)((oloc).y & 0xFF))
#ifdef SAFE_FIX
#define OBJ_LOC_VAL_TO_FIX(value) (fix_make((value >> 8), ((value & 0xFF) << 8)))
#else
#define OBJ_LOC_VAL_TO_FIX(value) (((fix)value)<<8)
#endif
typedef struct {
char ph;
byte type;
short current_hp;
ubyte make_info; // maker, as in Zortech MK III laser rifle or whatever
ubyte current_frame; // animdata
ubyte time_remainder; // animdata
uchar inst_flags; // flags for instance data. right now 0x01 is used by Mahk's render tricks
} ObjInfo;
typedef struct {
int ph;
byte type;
short current_hp;
ubyte make_info; // maker, as in Zortech MK III laser rifle or whatever
ubyte current_frame; // animdata
ubyte time_remainder; // animdata
uchar inst_flags; // flags for instance data. right now 0x01 is used by Mahk's render tricks
} old_ObjInfo;
#ifdef HASH_OBJECTS
# define OBJ_HASH_ENTRIES 512
# define OBJ_HASH_HEAD_ENTRIES 256
# define OBJ_HASH_HEAD_ENTRIES_START (OBJ_HASH_ENTRIES - OBJ_HASH_HEAD_ENTRIES)
# define OBJ_HASH_FUNC(bin) ((((((bin).sq.x) << 2) + ((bin).sq.y)) & (OBJ_HASH_HEAD_ENTRIES - 1)) + OBJ_HASH_HEAD_ENTRIES_START)
# define ObjRefHead(bin) (objHashTable[ObjGetHashElem((bin),FALSE)].ref) /* don't change this */
#else
# define ObjRefHead(bin) (MAP_GET_XY((bin).sq.x,(bin).sq.y))->objRef
#endif
// ////////////////////////////////
// //
////////////////////////////// WASN'T THAT EASY?
typedef struct {
ObjRefStateBin bin;
} ObjRefState;
typedef struct {
ObjRefStateBin bin;
ObjRefStateInfo info;
} oldObjRefState;
// The following macros perform simple comparing and copying operations.
// If your structures are immensely complicated, you can turn them into
// functions. It will slow things down, though.
// isnt it neat that you cant do sizeof(ObjRefStateBin) in a #if
// i love cpp with an unholy, inhuman, and altogether pathetic way
#if (SIZEOF_AN_OBJREFSTATEBIN==4)
#define ObjRefStateBinEqual(bin1,bin2) (*((int *)(&bin1))==*((int *)(&bin2)))
#elif (SIZEOF_AN_OBJREFSTATEBIN==2)
#define ObjRefStateBinEqual(bin1,bin2) (*((short *)(&bin1))==*((short *)(&bin2)))
#elif (SIZEOF_AN_OBJREFSTATEBIN==1)
#define ObjRefStateBinEqual(bin1,bin2) (*((char *)(&bin1))==*((char *)(&bin2)))
#else
#define ObjRefStateBinEqual(bin1,bin2) (!memcmp(&(bin1),&(bin2),sizeof(ObjRefStateBin)))
#endif
#define ObjRefStateBinCopy(srcbin, dstbin) do {dstbin = srcbin;} while (0)
#ifndef NO_OBJ_REF_STATE_INFO
# if (SIZEOF_AN_OBJREFSTATEINFO==4)
# define ObjRefStateInfoEqual(info1,info2) (*((int *)(&info1))==*((int *)(&info2)))
# elif (SIZEOF_AN_OBJREFSTATEINFO==2)
# define ObjRefStateInfoEqual(info1,info2) (*((short *)(&info1))==*((short *)(&info2)))
# elif (SIZEOF_AN_OBJREFSTATEINFO==1)
# define ObjRefStateInfoEqual(info1,info2) (*((char *)(&info1))==*((char *)(&info2)))
# else
# define ObjRefStateInfoEqual(info1,info2) (!memcmp(&(info1),&(info2),sizeof(ObjRefStateInfo)))
# endif
# define ObjRefStateInfoCopy(srcinfo, dstinfo) do {dstinfo = srcinfo;} while (0)
#endif
#if (SIZEOF_AN_OBJLOC==4)
#define ObjLocEqual(bin1, bin2) (*((int *)(&bin1))==*((int *)(&bin2)))
#elif (SIZEOF_AN_OBJLOC==2)
#define ObjLocEqual(bin1, bin2) (*((short *)(&bin1))==*((short *)(&bin2)))
#elif (SIZEOF_AN_OBJLOC==1)
#define ObjLocEqual(bin1, bin2) (*((char *)(&bin1))==*((char *)(&bin2)))
#else
#define ObjLocEqual(bin1, bin2) (!memcmp(&(bin1),&(bin2),sizeof(ObjLoc)))
#endif
#define ObjLocCopy(srcbin, dstbin) do {dstbin = srcbin;} while (0)
////////////////////////////// MORE STUFF YOU MUST CHANGE
// //
// ////////////////////////////////
//
// You can turn some of the following macros into functions, if they get complicated.
//
// These are all for the use of the debugging system. They should print
// a user-friendly representation of the appropriate structure into str,
// without a trailing newline.
#define ObjRefStateSprint(str,refstate)
#define ObjRefStateBinSprint(str,bin)
#define ObjRefStateInfoSprint(str,info)
#define ObjLocSprint(str,loc)
#define ObjInfoSprint(str,info)
// ////////////////////////////////
// //
////////////////////////////// END OF STUFF YOU MUST CHANGE
////////////////////////////////////////////////////////////
//
// Here are prototypes of a few functions you should define in
// objapp.c. Any macros above that you decided to turn into functions
// should also be defined in objapp.c.
//
void ObjInfoInit (ObjInfo *info);
//////////////////////////////
//
// This should initialize the following iterator. Nice name, huh?
void ObjRefStateBinIteratorInit (void);
//////////////////////////////
//
// After ObjRefStateBinIteratorInit () has been called, calling this
// should put a new valid ObjRefStateBin in bin every time it is called.
// It returns FALSE if it has already returned all valid bins (in which
// case the value of bin is undefined); otherwise it returns TRUE, of
// course.
//
// It can use static variables; the iterator is guaranteed to be active
// only once at a time.
bool ObjRefStateBinIterator (ObjRefStateBin *bin);
#endif //OBJAPP_H