1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #ifndef ULTIMA8_WORLD_ITEM_H
24 #define ULTIMA8_WORLD_ITEM_H
25
26 #include "ultima/ultima8/kernel/object.h"
27 #include "ultima/ultima8/graphics/shape_info.h"
28
29 #include "ultima/ultima8/usecode/intrinsics.h"
30 #include "ultima/ultima8/misc/box.h"
31 #include "ultima/ultima8/misc/point3.h"
32 #include "ultima/ultima8/misc/direction.h"
33
34 namespace Ultima {
35 namespace Ultima8 {
36
37 class Container;
38 class ShapeInfo;
39 class Shape;
40 class Gump;
41 class GravityProcess;
42
43 class Item : public Object {
44 friend class ItemFactory;
45
46 public:
47 Item();
48 ~Item() override;
49
ENABLE_RUNTIME_CLASSTYPE()50 ENABLE_RUNTIME_CLASSTYPE()
51
52 //! Get the Container this Item is in, if any. (0 if not in a Container)
53 ObjId getParent() const {
54 return _parent;
55 }
56
57 //! Set the parent container of this item.
setParent(ObjId p)58 void setParent(ObjId p) {
59 _parent = p;
60 }
61
62 //! Get the Container this Item is in, if any. (NULL if not in a Container)
63 Container *getParentAsContainer() const;
64
65 //! Get the top-most Container this Item is in, or the Item itself if not
66 //! in a container
67 Item *getTopItem();
68
69 //! Set item location. This strictly sets the location, and does not
70 //! even update CurrentMap
71 void setLocation(int32 x, int32 y, int32 z); // this only sets the loc.
72
73 //! Move an item. This moves an item to the new location, and updates
74 //! CurrentMap and fastArea if necessary.
75 virtual void move(int32 x, int32 y, int32 z);
76
77 //! Move, but with a point struct.
78 void move(const Point3 &pt);
79
80 //! Move an item. This moves an item to a container and updates
81 //! CurrentMap and fastArea if necessary.
82 //! \param container The container this item should be placed in
83 //! \return true if item was moved, false if failed
84 bool moveToContainer(Container *container, bool checkwghtvol = false);
85
86 //! Move an item to the Ethereal Void
87 void moveToEtherealVoid();
88
89 //! Move an item out of the Ethereal Void to where it originally was
90 void returnFromEtherealVoid();
91
92 //! Check if moving this item is stealing; call AvatarStoleSomething if so
93 void movedByPlayer();
94
95 //! Get the location of the top-most container this Item is in, or
96 //! this Item's location if not in a container.
97 void getLocationAbsolute(int32 &x, int32 &y, int32 &z) const;
98
99 //! Get this Item's location. Note that this does not return
100 //! 'usable' coordinates if the Item is contained or equipped.
101 inline void getLocation(int32 &x, int32 &y, int32 &z) const;
102
103 //! Get the Item's location using a Point3 struct.
104 inline void getLocation(Point3 &pt) const;
105
106 //! Get this Item's Z coordinate.
107 int32 getZ() const;
108
109 //! Set this Item's Z coordinate
setZ(int32 z)110 void setZ(int32 z) {
111 _z = z;
112 }
113
114 //! Get this Item's location in a ContainerGump. Undefined if the Item
115 //! is not in a Container.
116 void getGumpLocation(int32 &x, int32 &y) const;
117
118 //! Set the Item's location in a ContainerGump. NOP if the Item
119 //! is not in a Container.
120 void setGumpLocation(int32 x, int32 y);
121
122 //! Randomize the Item's location in a ContainerGump. Effectively
123 //! this sets the coordinates to (255,255) and lets the ContainerGump
124 //! randomize the position when it is next opened.
125 void randomGumpLocation();
126
127 //! Get the world coordinates of the Item's centre. Undefined if the Item
128 //! is contained or equipped.
129 void getCentre(int32 &x, int32 &y, int32 &z) const;
130
131 //! Get the size of this item's 3D bounding box, in world coordinates.
132 inline void getFootpadWorld(int32 &x, int32 &y, int32 &z) const;
133
134 //! Get the size of this item's 3D bounding box, scaled as in the datafiles
135 //! (i.e., the dimensions are not in the same unit as world coordinates!)
136 inline void getFootpadData(int32 &x, int32 &y, int32 &z) const;
137
138 //! Get the Box this item occupies in the world. Undef if item is contained
139 Box getWorldBox() const;
140
141 //! Get all flags
getFlags()142 inline uint16 getFlags() const {
143 return _flags;
144 }
145
146 //! Does this item have any of the given flags mask set
hasFlags(uint16 flags)147 inline bool hasFlags(uint16 flags) const {
148 return (_flags & flags) != 0;
149 }
150
151 //! Set the flags set in the given mask.
setFlag(uint32 mask)152 void setFlag(uint32 mask) {
153 _flags |= mask;
154 }
155
setFlagRecursively(uint32 mask)156 virtual void setFlagRecursively(uint32 mask) {
157 setFlag(mask);
158 }
159
160 //! Clear the flags set in the given mask.
clearFlag(uint32 mask)161 void clearFlag(uint32 mask) {
162 _flags &= ~mask;
163 }
164
165 //! Set _extendedFlags
setExtFlags(uint32 f)166 void setExtFlags(uint32 f) {
167 _extendedFlags = f;
168 }
169
170 //! Get _extendedFlags
getExtFlags()171 inline uint32 getExtFlags() const {
172 return _extendedFlags;
173 }
174
175 //! Does item have any of the given extended flags
hasExtFlags(uint32 flags)176 inline bool hasExtFlags(uint32 flags) const {
177 return (_extendedFlags & flags) != 0;
178 }
179
180 //! Set the _extendedFlags set in the given mask.
setExtFlag(uint32 mask)181 void setExtFlag(uint32 mask) {
182 _extendedFlags |= mask;
183 }
184
185 //! Clear the _extendedFlags set in the given mask.
clearExtFlag(uint32 mask)186 void clearExtFlag(uint32 mask) {
187 _extendedFlags &= ~mask;
188 }
189
190 //! Get this Item's shape number
getShape()191 uint32 getShape() const {
192 return _shape;
193 }
194
195 //! Set this Item's shape number
196 void setShape(uint32 shape);
197
198 //! Get this Item's frame number
getFrame()199 uint32 getFrame() const {
200 return _frame;
201 }
202
203 //! Set this Item's frame number
setFrame(uint32 frame)204 void setFrame(uint32 frame) {
205 _frame = frame;
206 }
207
208 //! Get this Item's quality (a.k.a. 'Q')
getQuality()209 uint16 getQuality() const {
210 return _quality;
211 }
212
213 //! Set this Item's quality (a.k.a 'Q');
setQuality(uint16 quality)214 void setQuality(uint16 quality) {
215 _quality = quality;
216 }
217
218 //! Get the 'NpcNum' of this Item. Note that this can represent various
219 //! things depending on the family of this Item.
getNpcNum()220 uint16 getNpcNum() const {
221 return _npcNum;
222 }
223
224 //! Set the 'NpcNum' of this Item. Note that this can represent various
225 //! things depending on the family of this Item.
setNpcNum(uint16 npcnum)226 void setNpcNum(uint16 npcnum) {
227 _npcNum = npcnum;
228 }
229
230 //! Get the 'MapNum' of this Item. Note that this can represent various
231 //! things depending on the family of this Item.
getMapNum()232 uint16 getMapNum() const {
233 return _mapNum;
234 }
235
236 //! Set the 'MapNum' of this Item. Note that this can represent various
237 //! things depending on the family of this Item.
setMapNum(uint16 mapnum)238 void setMapNum(uint16 mapnum) {
239 _mapNum = mapnum;
240 }
241
242 //! Get the ShapeInfo object for this Item. (The pointer will be cached.)
243 inline const ShapeInfo *getShapeInfo() const;
244
245 //! Get the ShapeInfo object for this Item from the game instance.
246 virtual const ShapeInfo *getShapeInfoFromGameInstance() const;
247
248 //! Get the Shape object for this Item. (The pointer will be cached.)
249 const Shape *getShapeObject() const;
250
251 //! Get the family of the shape number of this Item. (This is a
252 //! member of the ShapeInfo object.)
253 uint16 getFamily() const;
254
255 //! Check if we can merge with another item.
256 bool canMergeWith(Item *other);
257
258 //! Get the open ContainerGump for this Item, if any. (NULL if not open.)
getGump()259 ObjId getGump() const {
260 return _gump;
261 }
262 //! Call this to notify the Item's open Gump has closed.
263 void clearGump(); // set gump to 0 and clear the GUMP_OPEN flag
264 //! Open a gump with the given shape for this Item
265 ObjId openGump(uint32 gumpshape);
266 //! Close this Item's gump, if any
267 void closeGump();
268
269 //! Destroy self.
270 virtual void destroy(bool delnow = false);
271
272 //! Check if this item overlaps another item in 3D world-space
273 bool overlaps(const Item &item2) const;
274
275 //! Check if this item overlaps another item in the xy dims in 3D space
276 bool overlapsxy(const Item &item2) const;
277
278 //! Check if this item is on top of another item
279 bool isOn(const Item &item2) const;
280
281 //! Check if this item is on completely on top of another item
282 bool isCompletelyOn(const Item &item2) const;
283
284 //! Check if the centre of this item is on top of another item
285 bool isCentreOn(const Item &item2) const;
286
287 //! Check if the item is currently entirely visible on screen
288 bool isOnScreen() const;
289
290 //! Check if the item is currently partly visible on screen
291 bool isPartlyOnScreen() const;
292
293 //! Check if this item can exist at the given coordinates
294 bool canExistAt(int32 x, int32 y, int32 z, bool needsupport = false) const;
295
296 //! Get direction from centre to another item's centre.
297 //! Undefined if either item is contained or equipped.
298 Direction getDirToItemCentre(const Item &item2) const;
299
300 //! Same as above, but from a fixed point.
301 Direction getDirToItemCentre(const Point3 &pt) const;
302
303 //! get 'distance' to other item. This is the maximum of the differences
304 //! between the x, y (and possibly z) coordinates of the items.
305 int getRange(const Item &item2, bool checkz = false) const;
306
307 //! get 'distance' to other item if it's visible (ie, there's nothing blocking the path)
308 int getRangeIfVisible(const Item &item2) const;
309
310 //! Check if this item can reach another item. (This includes LoS.)
311 //! \param other item to be reached
312 //! \param range range
313 //! \param x x coordinate of other to use, If zero, use real coords.
314 //! \param y y coordinate of other to use
315 //! \param z z coordinate of other to use.
316 bool canReach(Item *other, int range, int32 x = 0, int32 y = 0, int32 z = 0);
317
318 //! Move the object to (x,y,z) colliding with objects in the way.
319 //! \param teleport move without colliding with objects between source and
320 //! destination
321 //! \param force force the object to get to the destination without being
322 //! blocked by solid objects
323 //! \param hititem if non-NULL, this is set to (one of) the item(s)
324 //! blocking the movement, or to zero if nothing blocked it
325 //! \param dirs if non-NULL, this is set to a bitmask of the x/y/z
326 // directions in which movement was blocked (bit 0=x,1=y,2=z)
327 //! \returns 0-0x4000 representing how far it got.
328 //! 0 = didn't move
329 //! 0x4000 = reached destination
330 //! \note This can destroy the object
331 virtual int32 collideMove(int32 x, int32 y, int32 z, bool teleport, bool force,
332 ObjId *hititem = 0, uint8 *dirs = 0);
333
334 //! Make the item move up (delta>0) or down (delta<0),
335 //! including any items on top of it
336 //! \param delta distance in Z-direction to move
337 //! \returns 0-0x4000 representing how far it got.
338 //! 0 = didn't move
339 //! 0x4000 = reached destination
340 int32 ascend(int delta);
341
342 //! Make the item fall down.
343 //! This creates a GravityProcess to do the actual work if the Item
344 //! doesn't already have one.
345 void fall();
346
347 //! Make any items on top of this Item fall down and notify any supporting
348 //! items that we're gone by calling the 'release' event.
349 //! Note that this Item has to be moved away right after calling grab(),
350 //! since otherwise the items will immediately hit this Item again.
351 void grab();
352
353 //! Hurl the item in the given direction
354 void hurl(int xs, int ys, int zs, int grav);
355
356 //! Set the PID of the GravityProcess for this Item. There should be only one.
setGravityPID(ProcId pid)357 void setGravityPID(ProcId pid) {
358 assert(_gravityPid == 0 || pid == 0);
359 _gravityPid = pid;
360 }
361
362 //! Get the PID of the GravityProcess for this Item (or 0)
getGravityPID()363 ProcId getGravityPID() const {
364 return _gravityPid;
365 }
366
367 //! Get the GravityProcess of this Item, creating it if necessary
368 virtual GravityProcess *ensureGravityProcess();
369
370 //! Get the weight of this Item
371 virtual uint32 getWeight() const;
372
373 //! Get the weight of this Item and its contents, if any
374 virtual uint32 getTotalWeight() const;
375
376 //! Get the volume this item takes up in a container
377 virtual uint32 getVolume() const;
378
379 //! explode with explosion type (0,1,2), whether to destroy the item,
380 //! and whether to cause splash damage.
381 void explode(int explosion_type, bool destroy_item, bool cause_damage = true);
382
383 //! get the damage type this object does when hitting something
384 virtual uint16 getDamageType() const;
385
386 //! receive a hit
387 //! \param other The item delivering the hit
388 //! \param dir The direction the hit is coming from (or inverse? CHECKME!)
389 //! \param damage The force of the hit. Zero for default
390 //! \param type The type of damage done. Zero for default
391 virtual void receiveHit(ObjId other, Direction dir, int damage, uint16 type);
392
393 //! fire the given weapon type in the given direction from location x, y, z.
394 uint16 fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype, bool findtarget);
395
396 //! get the distance (in map tiles) if we were to fire in this direction to "other"
397 //! and could hit, otherwise return 0.
398 uint16 fireDistance(const Item *other, Direction dir, int16 xoff, int16 yoff, int16 zoff) const;
399
400 //! get damage points, used in Crusader for item damage.
getDamagePoints()401 uint8 getDamagePoints() const {
402 return _damagePoints;
403 }
404
405 //! set damage points, used in Crusader for item damage.
setDamagePoints(uint8 points)406 void setDamagePoints(uint8 points) {
407 _damagePoints = points;
408 }
409
410 //! Get the right Z which an attacker should aim for, given the attacker's z.
411 //! (Crusader only)
412 int32 getTargetZRelativeToAttackerZ(int32 attackerz) const;
413
414 //! count nearby objects of a given shape
415 unsigned int countNearby(uint32 shape, uint16 range);
416
417 //! can this item be dragged?
418 bool canDrag();
419
420 //! how far can this item be thrown?
421 //! \return range, or 0 if item can't be thrown
422 int getThrowRange();
423
424 //! Check this Item against the given loopscript
425 //! \param script The loopscript to run
426 //! \param scriptsize The size (in bytes) of the loopscript
427 //! \return true if the item matches, false otherwise
428 bool checkLoopScript(const uint8 *script, uint32 scriptsize) const;
429
430 uint32 callUsecodeEvent_look(); // event 0
431 uint32 callUsecodeEvent_use(); // event 1
432 uint32 callUsecodeEvent_anim(); // event 2
433 uint32 callUsecodeEvent_cachein(); // event 4
434 uint32 callUsecodeEvent_hit(ObjId hitted, int16 hitforce); // event 5
435 uint32 callUsecodeEvent_gotHit(ObjId hitter, int16 hitforce);// event 6
436 uint32 callUsecodeEvent_hatch(); // event 7
437 uint32 callUsecodeEvent_schedule(uint32 time); // event 8
438 uint32 callUsecodeEvent_release(); // event 9
439 uint32 callUsecodeEvent_equip(); // event A
440 uint32 callUsecodeEvent_equipWithParam(ObjId param); // event A
441 uint32 callUsecodeEvent_unequip(); // event B
442 uint32 callUsecodeEvent_unequipWithParam(ObjId param); // event B
443 uint32 callUsecodeEvent_combine(); // event C
444 uint32 callUsecodeEvent_calledFromAnim(); // event E
445 uint32 callUsecodeEvent_enterFastArea(); // event F
446 uint32 callUsecodeEvent_leaveFastArea(); // event 10
447 uint32 callUsecodeEvent_cast(uint16 unk); // event 11
448 uint32 callUsecodeEvent_justMoved(); // event 12
449 uint32 callUsecodeEvent_AvatarStoleSomething(uint16 unk); // event 14
450 uint32 callUsecodeEvent_guardianBark(int16 unk); // event 15 (Ultima)
451 uint32 callUsecodeEvent_unhatch(); // event 15 (Crusader)
452
453 uint32 use();
454
455 //! Get lerped location.
getLerped(int32 & xp,int32 & yp,int32 & zp)456 inline void getLerped(int32 &xp, int32 &yp, int32 &zp) const {
457 xp = _ix;
458 yp = _iy;
459 zp = _iz;
460 }
461
462 //! Do lerping for an in between frame (0-256)
463 //! The result can be retrieved with getLerped(x,y,z)
464 //! \param factor The lerp factor: 0 is start of move, 256 is end of move
doLerp(int32 factor)465 inline void doLerp(int32 factor) {
466 // Should be noted that this does indeed limit us to 'only' 24bit coords
467 // not that it matters because on disk they are unsigned 16 bit
468
469 if (factor == 256) {
470 _ix = _lNext._x;
471 _iy = _lNext._y;
472 _iz = _lNext._z;
473 } else if (factor == 0) {
474 _ix = _lPrev._x;
475 _iy = _lPrev._y;
476 _iz = _lPrev._z;
477 } else {
478 #if 1
479 // This way while possibly slower is more accurate
480 _ix = ((_lPrev._x * (256 - factor) + _lNext._x * factor) >> 8);
481 _iy = ((_lPrev._y * (256 - factor) + _lNext._y * factor) >> 8);
482 _iz = ((_lPrev._z * (256 - factor) + _lNext._z * factor) >> 8);
483 #else
484 _ix = _lPrev.x + (((_lNext.x - _lPrev.x) * factor) >> 8);
485 _iy = _lPrev.y + (((_lNext.y - _lPrev.y) * factor) >> 8);
486 _iz = _lPrev.z + (((_lNext.z - _lPrev.z) * factor) >> 8);
487 #endif
488 }
489 }
490
491 //! Setup the lerped info for this gametick and animate the item
492 void setupLerp(int32 gametick);
493
494 //! The item has entered the fast area
495 virtual uint32 enterFastArea();
496
497 //! The item has left the fast area
498 //! \note This can destroy the object
499 virtual void leaveFastArea();
500
501 //! dump some info about this item to pout
502 void dumpInfo() const override;
503
504 bool loadData(Common::ReadStream *rs, uint32 version);
505 void saveData(Common::WriteStream *ws) override;
506
507 // Intrinsics
508 INTRINSIC(I_touch);
509 INTRINSIC(I_getX);
510 INTRINSIC(I_getY);
511 INTRINSIC(I_getZ);
512 INTRINSIC(I_getCX);
513 INTRINSIC(I_getCY);
514 INTRINSIC(I_getCZ);
515 INTRINSIC(I_getPoint);
516 INTRINSIC(I_getShape);
517 INTRINSIC(I_setShape);
518 INTRINSIC(I_getFrame);
519 INTRINSIC(I_setFrame);
520 INTRINSIC(I_getQuality);
521 INTRINSIC(I_getUnkEggType);
522 INTRINSIC(I_setUnkEggType);
523 INTRINSIC(I_getQuantity);
524 INTRINSIC(I_getContainer);
525 INTRINSIC(I_getRootContainer);
526 INTRINSIC(I_getQ);
527 INTRINSIC(I_getQHi);
528 INTRINSIC(I_getQLo);
529 INTRINSIC(I_setQ);
530 INTRINSIC(I_setQHi);
531 INTRINSIC(I_setQLo);
532 INTRINSIC(I_setQuality);
533 INTRINSIC(I_setQuantity);
534 INTRINSIC(I_setQAndCombine);
535 INTRINSIC(I_getFamily);
536 INTRINSIC(I_getTypeFlag);
537 INTRINSIC(I_getStatus);
538 INTRINSIC(I_orStatus);
539 INTRINSIC(I_andStatus);
540 INTRINSIC(I_getFootpadData);
541 INTRINSIC(I_overlaps);
542 INTRINSIC(I_overlapsXY);
543 INTRINSIC(I_isOn);
544 INTRINSIC(I_isCompletelyOn);
545 INTRINSIC(I_isCentreOn);
546 INTRINSIC(I_isInNpc);
547 INTRINSIC(I_ascend);
548 INTRINSIC(I_getWeight);
549 INTRINSIC(I_getWeightIncludingContents);
550 INTRINSIC(I_getVolume);
551 INTRINSIC(I_bark);
552 INTRINSIC(I_getMapArray);
553 INTRINSIC(I_setMapArray);
554 INTRINSIC(I_getNpcNum);
555 INTRINSIC(I_setNpcNum);
556 INTRINSIC(I_getDirToCoords);
557 INTRINSIC(I_getDirFromCoords);
558 INTRINSIC(I_getDirToItem);
559 INTRINSIC(I_getDirFromItem);
560 INTRINSIC(I_getDirFromTo16);
561 INTRINSIC(I_getClosestDirectionInRange);
562 INTRINSIC(I_look);
563 INTRINSIC(I_use);
564 INTRINSIC(I_gotHit);
565 INTRINSIC(I_enterFastArea);
566 INTRINSIC(I_cast);
567 INTRINSIC(I_ask);
568 INTRINSIC(I_getSliderInput);
569 INTRINSIC(I_openGump);
570 INTRINSIC(I_closeGump);
571 INTRINSIC(I_create);
572 INTRINSIC(I_legalCreateAtPoint);
573 INTRINSIC(I_legalCreateAtCoords);
574 INTRINSIC(I_legalCreateInCont);
575 INTRINSIC(I_push);
576 INTRINSIC(I_pop);
577 INTRINSIC(I_popToCoords);
578 INTRINSIC(I_popToContainer);
579 INTRINSIC(I_popToEnd);
580 INTRINSIC(I_destroy);
581 INTRINSIC(I_move);
582 INTRINSIC(I_legalMoveToPoint);
583 INTRINSIC(I_legalMoveToContainer);
584 INTRINSIC(I_hurl);
585 INTRINSIC(I_shoot);
586 INTRINSIC(I_fall);
587 INTRINSIC(I_grab);
588 INTRINSIC(I_igniteChaos);
589 INTRINSIC(I_getFamilyOfType);
590 INTRINSIC(I_getEtherealTop);
591 INTRINSIC(I_guardianBark);
592 INTRINSIC(I_getSurfaceWeight);
593 INTRINSIC(I_isExplosive);
594 INTRINSIC(I_receiveHit);
595 INTRINSIC(I_explode);
596 INTRINSIC(I_canReach);
597 INTRINSIC(I_getRange);
598 INTRINSIC(I_getRangeIfVisible);
599 INTRINSIC(I_isCrusTypeNPC);
600 INTRINSIC(I_setBroken);
601 INTRINSIC(I_inFastArea);
602 INTRINSIC(I_equip);
603 INTRINSIC(I_unequip);
604 INTRINSIC(I_avatarStoleSomething);
605 INTRINSIC(I_isPartlyOnScreen);
606 INTRINSIC(I_fireWeapon);
607 INTRINSIC(I_fireDistance);
608
609 private:
610 uint32 _shape; // DO NOT modify this directly! Always use setShape()!
611
612 protected:
613 uint32 _frame;
614
615 int32 _x, _y, _z; // world coordinates
616 uint16 _flags;
617 uint16 _quality;
618 uint16 _npcNum;
619 uint16 _mapNum;
620
621 uint32 _extendedFlags; // pentagram's own flags
622
623 ObjId _parent; // objid container this item is in (or 0 for top-level items)
624
625 mutable const Shape *_cachedShape;
626 mutable const ShapeInfo *_cachedShapeInfo;
627
628 // This is stuff that is used for displaying and interpolation
629 struct Lerped {
LerpedLerped630 Lerped() : _x(0), _y(0), _z(0), _shape(0), _frame(0) {};
631 int32 _x, _y, _z;
632 uint32 _shape, _frame;
633 };
634
635 Lerped _lPrev; // Previous state (relative to camera)
636 Lerped _lNext; // Next (current) state (relative to camera)
637 int32 _ix, _iy, _iz; // Interpolated position in camera space
638
639 ObjId _gump; // Item's gump
640 ProcId _gravityPid; // Item's GravityTracker (or 0)
641
642 uint8 _damagePoints; // Damage points, used for item damage in Crusader
643
644 //! True if this is a Robot shape (in a fixed list)
645 bool isRobotCru() const;
646
647 //! Scale a received damage value based on the current difficulty level
648 //! and the type of object this is.
649 int scaleReceivedDamageCru(int damage, uint16 type) const;
650
651 private:
652
653 //! Call a Usecode Event. Use the separate functions instead!
654 uint32 callUsecodeEvent(uint32 event, const uint8 *args = 0, int argsize = 0);
655
656 //! The gametick setupLerp was last called on
657 int32 _lastSetup;
658
659 //! Animate the item (called by setupLerp)
660 void animateItem();
661
662 //! The U8 version of receiveHit
663 void receiveHitU8(ObjId other, Direction dir, int damage, uint16 type);
664
665 //! The Crusader version of receiveHit
666 void receiveHitCru(ObjId other, Direction dir, int damage, uint16 type);
667
668 public:
669 enum statusflags {
670 FLG_DISPOSABLE = 0x0002, //!< Item is discarded on map change
671 FLG_OWNED = 0x0004, //!< Item is owned by avatar
672 FLG_CONTAINED = 0x0008, //!< Item is in a container
673 FLG_INVISIBLE = 0x0010, //!< Item is invisible
674 FLG_FLIPPED = 0x0020, //!< Item is flipped horizontally
675 FLG_IN_NPC_LIST = 0x0040, //!< Item is a NPC
676 FLG_FAST_ONLY = 0x0080, //!< Item is discarded when leaving fast area
677 FLG_GUMP_OPEN = 0x0100, //!< Item has a gump open
678 FLG_EQUIPPED = 0x0200, //!< Item is equipped
679 FLG_BOUNCING = 0x0400, //!< Item has bounced
680 FLG_ETHEREAL = 0x0800, //!< Item is in the ethereal list - confirmed same meaning in crusader
681 FLG_HANGING = 0x1000, //!< Item is suspended in the air
682 FLG_FASTAREA = 0x2000, //!< Item is in the fast area
683 FLG_LOW_FRICTION = 0x4000, //!< Item has low friction
684 FLG_BROKEN = 0x8000 //!< Item is broken - Crusader only - broken items are not targetable.
685 };
686
687 enum extflags {
688 EXT_FIXED = 0x0001, //!< Item came from FIXED
689 EXT_INCURMAP = 0x0002, //!< Item is in a CurrentMap display list
690 EXT_LERP_NOPREV = 0x0008, //!< Item can't be lerped this frame
691 EXT_HIGHLIGHT = 0x0010, //!< Item should be Painted highlighted
692 EXT_CAMERA = 0x0020, //!< Item is being followed by the camera
693 EXT_SPRITE = 0x0040, //!< Item is a sprite
694 EXT_TRANSPARENT = 0x0080, //!< Item should be painted transparent
695 EXT_PERMANENT_NPC = 0x0100, //!< Item is a permanent NPC
696 EXT_TARGET = 0x0200, //!< Item is the current reticle target in Crusader
697 EXT_FEMALE = 0x8000 //!< Item is Crusader Female NPC (controls sfx)
698 };
699 };
700
getShapeInfo()701 inline const ShapeInfo *Item::getShapeInfo() const {
702 if (!_cachedShapeInfo)
703 _cachedShapeInfo = getShapeInfoFromGameInstance();
704 return _cachedShapeInfo;
705 }
706
getFootpadData(int32 & X,int32 & Y,int32 & Z)707 inline void Item::getFootpadData(int32 &X, int32 &Y, int32 &Z) const {
708 const ShapeInfo *si = getShapeInfo();
709 Z = si->_z;
710
711 if (_flags & Item::FLG_FLIPPED) {
712 X = si->_y;
713 Y = si->_x;
714 } else {
715 X = si->_x;
716 Y = si->_y;
717 }
718 }
719
720 // like getFootpadData, but scaled to world coordinates
getFootpadWorld(int32 & X,int32 & Y,int32 & Z)721 inline void Item::getFootpadWorld(int32 &X, int32 &Y, int32 &Z) const {
722 const ShapeInfo *si = getShapeInfo();
723 si->getFootpadWorld(X, Y, Z, _flags & Item::FLG_FLIPPED);
724 }
725
getLocation(int32 & X,int32 & Y,int32 & Z)726 inline void Item::getLocation(int32 &X, int32 &Y, int32 &Z) const {
727 X = _x;
728 Y = _y;
729 Z = _z;
730 }
731
getLocation(Point3 & pt)732 inline void Item::getLocation(Point3 &pt) const {
733 pt.x = _x;
734 pt.y = _y;
735 pt.z = _z;
736 }
737
738 } // End of namespace Ultima8
739 } // End of namespace Ultima
740
741 #endif
742