3 #include "common/llist.h"
4 #include "ObjManager.h"
5 #include "ObjManager.fdh"
7 static Object ZERO_OBJECT
;
8 static Player ZERO_PLAYER
;
10 Object
*firstobject
= NULL
, *lastobject
= NULL
;
11 Object
*lowestobject
= NULL
, *highestobject
= NULL
;
14 void c------------------------------() {}
17 Object
*CreateObject(int x
, int y
, int type
, int xinertia
, int yinertia
,
18 int dir
, Object
*linkedobject
, uint32_t createflags
)
22 // create the structure
23 if (type
!= OBJ_PLAYER
)
26 *o
= ZERO_OBJECT
; // safely clears all members
30 Player
*p
= new Player
;
37 o
->flags
= objprop
[type
].defaultflags
;
38 o
->DamageText
= new FloatText(SPR_REDNUMBERS
);
40 o
->x
= x
- (sprites
[o
->sprite
].spawn_point
.x
<< CSF
);
41 o
->y
= y
- (sprites
[o
->sprite
].spawn_point
.y
<< CSF
);
43 o
->xinertia
= xinertia
;
44 o
->yinertia
= yinertia
;
45 o
->linkedobject
= linkedobject
;
48 LL_ADD_END(o
, prev
, next
, firstobject
, lastobject
);
49 LL_ADD_END(o
, lower
, higher
, lowestobject
, highestobject
);
51 // set it's initial blocked states, but do not update blockedstates on objects starting
52 // with nullsprite-- the reason is for objects whose sprite is set after being spawned
53 if (o
->sprite
!= SPR_NULL
)
54 o
->UpdateBlockStates(ALLDIRMASK
);
56 if (!(createflags
& CF_NO_SPAWN_EVENT
))
62 Object
*CreateObject(int x
, int y
, int type
)
64 return CreateObject(x
, y
, type
, 0, 0, RIGHT
, NULL
, CF_DEFAULT
);
68 void c------------------------------() {}
71 // update the blocked states of all objects
72 void Objects::UpdateBlockStates(void)
74 Object
*o
= firstobject
;
77 o
->lastblockl
= o
->blockl
;
78 o
->lastblockr
= o
->blockr
;
79 o
->lastblocku
= o
->blocku
;
80 o
->lastblockd
= o
->blockd
;
82 o
->UpdateBlockStates(ALLDIRMASK
);
87 // returns true if the bounding boxes of the two given objects are touching
88 bool hitdetect(Object
*o1
, Object
*o2
)
91 int32_t rect1x1
, rect1y1
, rect1x2
, rect1y2
;
92 int32_t rect2x1
, rect2y1
, rect2x2
, rect2y2
;
94 // get the sprites used by the two objects
98 // get the bounding rectangle of the first object
99 rect1x1
= o1
->x
+ (s1
->bbox
.x1
<< CSF
);
100 rect1x2
= o1
->x
+ (s1
->bbox
.x2
<< CSF
);
101 rect1y1
= o1
->y
+ (s1
->bbox
.y1
<< CSF
);
102 rect1y2
= o1
->y
+ (s1
->bbox
.y2
<< CSF
);
104 // get the bounding rectangle of the second object
105 rect2x1
= o2
->x
+ (s2
->bbox
.x1
<< CSF
);
106 rect2x2
= o2
->x
+ (s2
->bbox
.x2
<< CSF
);
107 rect2y1
= o2
->y
+ (s2
->bbox
.y1
<< CSF
);
108 rect2y2
= o2
->y
+ (s2
->bbox
.y2
<< CSF
);
110 // find out if the rectangles overlap
111 if ((rect1x1
< rect2x1
) && (rect1x2
< rect2x1
)) return false;
112 if ((rect1x1
> rect2x2
) && (rect1x2
> rect2x2
)) return false;
113 if ((rect1y1
< rect2y1
) && (rect1y2
< rect2y1
)) return false;
114 if ((rect1y1
> rect2y2
) && (rect1y2
> rect2y2
)) return false;
119 // returns true if the solidity boxes of the two given objects are touching
120 bool solidhitdetect(Object
*o1
, Object
*o2
)
123 int32_t rect1x1
, rect1y1
, rect1x2
, rect1y2
;
124 int32_t rect2x1
, rect2y1
, rect2x2
, rect2y2
;
126 // get the sprites used by the two objects
130 // get the bounding rectangle of the first object
131 rect1x1
= o1
->x
+ (s1
->solidbox
.x1
<< CSF
);
132 rect1x2
= o1
->x
+ (s1
->solidbox
.x2
<< CSF
);
133 rect1y1
= o1
->y
+ (s1
->solidbox
.y1
<< CSF
);
134 rect1y2
= o1
->y
+ (s1
->solidbox
.y2
<< CSF
);
136 // get the bounding rectangle of the second object
137 rect2x1
= o2
->x
+ (s2
->solidbox
.x1
<< CSF
);
138 rect2x2
= o2
->x
+ (s2
->solidbox
.x2
<< CSF
);
139 rect2y1
= o2
->y
+ (s2
->solidbox
.y1
<< CSF
);
140 rect2y2
= o2
->y
+ (s2
->solidbox
.y2
<< CSF
);
142 // find out if the rectangles overlap
143 if ((rect1x1
< rect2x1
) && (rect1x2
< rect2x1
)) return false;
144 if ((rect1x1
> rect2x2
) && (rect1x2
> rect2x2
)) return false;
145 if ((rect1y1
< rect2y1
) && (rect1y2
< rect2y1
)) return false;
146 if ((rect1y1
> rect2y2
) && (rect1y2
> rect2y2
)) return false;
152 void c------------------------------() {}
155 // runs all entity AI routines
156 void Objects::RunAI(void)
160 // because we handle objects in order of their creation and have a separate list
161 // for display order, we can't ever run AI twice in a frame because of z-order
162 // rearrangement, and 2) objects created by other objects are added to the end of
163 // the list and given a chance to run their AI routine before being displayed.
172 // the most important thing it does is apply x/y inertia to the objects.
173 void Objects::PhysicsSim(void)
176 int xinertia
, yinertia
;
180 if (o
!= player
&& !o
->deleted
) // player is moved in PDoPhysics
182 if (!(o
->flags
& FLAG_IGNORE_SOLID
) && \
183 !(o
->nxflags
& NXFLAG_NO_RESET_YINERTIA
))
185 if (o
->blockd
&& o
->yinertia
> 0) o
->yinertia
= 0;
186 if (o
->blocku
&& o
->yinertia
< 0) o
->yinertia
= 0;
189 // apply inertia to X,Y position
190 xinertia
= o
->xinertia
;
191 yinertia
= o
->yinertia
;
194 if (o
->nxflags
& NXFLAG_SLOW_X_WHEN_HURT
) xinertia
>>= 1;
195 if (o
->nxflags
& NXFLAG_SLOW_Y_WHEN_HURT
) yinertia
>>= 1;
198 o
->apply_xinertia(xinertia
);
199 o
->apply_yinertia(yinertia
);
201 // flag_solid_brick objects push player as they move
202 if (o
->flags
& FLAG_SOLID_BRICK
)
204 o
->PushPlayerOutOfWay(xinertia
, yinertia
);
206 else if (o
->damage
> 0)
208 // have enemies hurt you when you touch them
209 // (solid-brick objects do this in PHandleSolidBrickObjects)
210 if (hitdetect(o
, player
))
211 o
->DealContactDamage();
218 void c------------------------------() {}
221 // returns how many objects exist of the given type
222 int Objects::CountType(int objtype
)
229 if (o
->type
== objtype
)
236 // returns the first object of type objtype or NULL
237 Object
*Objects::FindByType(int objtype
)
242 if (o
->type
== objtype
)
250 void c------------------------------() {}
253 // free objects deleted earlier via ObjDel
254 void Objects::CullDeleted(void)
272 // deletes all objects. if delete_player is true, also deletes the player.
273 // used by load_pxe to reset the game in preperation for loading a new maplayer->
274 void Objects::DestroyAll(bool delete_player
)
291 // must do this last to avoid crashes as player ptr gets invalidated
297 memset(ID2Lookup
, 0, sizeof(ID2Lookup
));