summaryrefslogtreecommitdiff
path: root/src/uqm/element.h
blob: dd41340899319da0e849405dc4835e8623c13086 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
//Copyright Paul Reiche, Fred Ford. 1992-2002

/*
 *  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 2 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifndef UQM_ELEMENT_H_
#define UQM_ELEMENT_H_

#include "displist.h"
#include "units.h"
#include "velocity.h"
#include "libs/gfxlib.h"

#if defined(__cplusplus)
extern "C" {
#endif


#define NORMAL_LIFE 1

typedef HLINK HELEMENT;

// Bits for ELEMENT_FLAGS:
// bits 0 and 1 are now available
#define PLAYER_SHIP (1 << 2)
		// The ELEMENT is a player controlable ship, and not some bullet,
		// crew, asteroid, fighter, etc. This does not mean that the ship
		// is actually controlled by a human; it may be a computer.

#define APPEARING (1 << 3)
#define DISAPPEARING (1 << 4)
#define CHANGING (1 << 5)
		// The element's graphical representation has changed.

#define NONSOLID (1 << 6)
#define COLLISION (1 << 7)
#define IGNORE_SIMILAR (1 << 8)
#define DEFY_PHYSICS (1 << 9)

#define FINITE_LIFE (1 << 10)

#define PRE_PROCESS (1 << 11)
		// PreProcess() is to be called for the ELEMENT.
#define POST_PROCESS (1 << 12)

#define IGNORE_VELOCITY (1 << 13)
#define CREW_OBJECT (1 << 14)
#define BACKGROUND_OBJECT (1 << 15)
		// The BACKGROUND_OBJECT flag existed originally but wasn't used.
		// It can now be used for objects that never influence the state
		// of other elements; elements that have this flag set are not
		// included in the checksum used for netplay games.
		// It can be used for graphical mods that don't impede netplay.


#define HYPERJUMP_LIFE 15

#define NUM_EXPLOSION_FRAMES 12

#define GAME_SOUND_PRIORITY 2

typedef enum
{
	VIEW_STABLE,
	VIEW_SCROLL,
	VIEW_CHANGE
} VIEW_STATE;

typedef UWORD ELEMENT_FLAGS;

#define NO_PRIM NUM_PRIMS

typedef struct state
{
	POINT location;
	struct
	{
		FRAME frame;
		FRAME *farray;
	} image;
} STATE;


typedef struct element ELEMENT;

typedef void (ElementProcessFunc) (ELEMENT *ElementPtr);
typedef void (ElementCollisionFunc) (ELEMENT *ElementPtr0, POINT *pPt0,
			ELEMENT *ElementPtr1, POINT *pPt1);

// Any physical object in the simulation.
struct element
{
	// LINK elements; must be first
	HELEMENT pred, succ;

	ElementProcessFunc *preprocess_func;
	ElementProcessFunc *postprocess_func;
	ElementCollisionFunc *collision_func;
	ElementProcessFunc *death_func;

	// Player this element belongs to
	// -1: neutral (planets, asteroids, crew, etc.)
	//  0: Melee: bottom player; Full-game: the human player
	//  1: Melee: top player;    Full-game: the NPC opponent
	SIZE playerNr;

	ELEMENT_FLAGS state_flags;
	union
	{
		COUNT life_span;
		COUNT scan_node; /* Planetside: scan type and node id */
	};
	union
	{
		COUNT crew_level;
		COUNT hit_points;
		COUNT facing; /* Planetside: lava-spot direction of travel */
		COUNT cycle;
				/* Planetside: lightning cycle length */
	};
	union
	{
		BYTE mass_points;
				/* Planetside:
				 * - for living bio: Index in CreatureData, possibly OR'ed
				 *   with CREATURE_AWARE
				 * - for canned bio: value of creature
				 */
		// TODO: Use a different name for Planetside bio, like
		// BYTE bio_state;
	};
	union
	{
		BYTE turn_wait;
		BYTE sys_loc; /* IP flagship: location in system */
	};
	union
	{
		BYTE thrust_wait;
		BYTE blast_offset;
		BYTE next_turn; /* Battle: animation interframe for some elements */
	};
	BYTE colorCycleIndex;
			// Melee: used to cycle ion trails and warp shadows, and
			//        to cycle the ship color when fleeing.

	VELOCITY_DESC velocity;
	INTERSECT_CONTROL IntersectControl;
	COUNT PrimIndex;
	STATE current, next;

	void *pParent;
			// The ship this element belongs to.
	HELEMENT hTarget;
};

#define NEUTRAL_PLAYER_NUM  -1

static inline BOOLEAN
elementsOfSamePlayer (ELEMENT *ElementPtr0, ELEMENT *ElementPtr1)
{
	return ElementPtr0->playerNr == ElementPtr1->playerNr;
}

extern QUEUE disp_q;
// The maximum number of elements is chosen to provide a slight margin.
// Currently, it is maximum *known used* in Melee + 30
#define MAX_DISPLAY_ELEMENTS 150

#define MAX_DISPLAY_PRIMS 330
extern COUNT DisplayFreeList;
extern PRIMITIVE DisplayArray[MAX_DISPLAY_PRIMS];

#define AllocDisplayPrim() DisplayFreeList; \
								DisplayFreeList = GetSuccLink (GetPrimLinks (&DisplayArray[DisplayFreeList]))
#define FreeDisplayPrim(p) SetPrimLinks (&DisplayArray[p], END_OF_LIST, DisplayFreeList); \
								DisplayFreeList = (p)

#define GetElementStarShip(e,ppsd) do { *(ppsd) = (e)->pParent; } while (0)
#define SetElementStarShip(e,psd)  do { (e)->pParent = psd; } while (0)

#define MAX_CREW_SIZE 42
#define MAX_ENERGY_SIZE 42
#define MAX_SHIP_MASS 10
#define GRAVITY_MASS(m) ((m) > MAX_SHIP_MASS * 10)
#define GRAVITY_THRESHOLD (COUNT)255

#define OBJECT_CLOAKED(eptr) \
		(GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) >= NUM_PRIMS \
		|| (GetPrimType (&GLOBAL (DisplayArray[(eptr)->PrimIndex])) == STAMPFILL_PRIM \
		&& sameColor (GetPrimColor (&GLOBAL (DisplayArray[(eptr)->PrimIndex])), BLACK_COLOR)))
#define UNDEFINED_LEVEL 0

extern HELEMENT AllocElement (void);
extern void FreeElement (HELEMENT hElement);
#define PutElement(h) PutQueue (&disp_q, h)
#define InsertElement(h,i) InsertQueue (&disp_q, h, i)
#define GetHeadElement() GetHeadLink (&disp_q)
#define GetTailElement() GetTailLink (&disp_q)
#define LockElement(h,ppe) (*(ppe) = (ELEMENT*)LockLink (&disp_q, h))
#define UnlockElement(h) UnlockLink (&disp_q, h)
#define GetPredElement(l) _GetPredLink (l)
#define GetSuccElement(l) _GetSuccLink (l)
extern void RemoveElement (HLINK hLink);

// XXX: The following functions should not really be here
extern void spawn_planet (void);
extern void spawn_asteroid (ELEMENT *ElementPtr);
extern void do_damage (ELEMENT *ElementPtr, SIZE damage);
extern void crew_preprocess (ELEMENT *ElementPtr);
extern void crew_collision (ELEMENT *ElementPtr0, POINT *pPt0,
		ELEMENT *ElementPtr1, POINT *pPt1);
extern void AbandonShip (ELEMENT *ShipPtr, ELEMENT *TargetPtr,
		COUNT crew_loss);
extern BOOLEAN TimeSpaceMatterConflict (ELEMENT *ElementPtr);
extern COUNT PlotIntercept (ELEMENT *ElementPtr0,
		ELEMENT *ElementPtr1, COUNT max_turns, COUNT margin_of_error);

extern void InitGalaxy (void);
extern void MoveGalaxy (VIEW_STATE view_state, SIZE dx, SIZE dy);

extern BOOLEAN CalculateGravity (ELEMENT *ElementPtr);


#if defined(__cplusplus)
}
#endif

#endif /* UQM_ELEMENT_H_ */