1 #include "innocent/actor.h"
3 #include "common/rect.h"
5 #include "innocent/innocent.h"
6 #include "innocent/logic.h"
7 #include "innocent/room.h"
8 #include "innocent/util.h"
13 Actor::Actor(const CodePointer
&code
) : Animation(code
, Common::Point()) {
14 byte
*header
= code
.code();
15 _base
= header
- code
.offset();
16 snprintf(_debugInfo
, 50, "actor at %s", +code
);
22 _attentionNeeded
= false;
24 Engine::instance().logic()->addAnimation(this);
29 void Actor::setAnimation(const CodePointer
&anim
) {
30 debugC(3, kDebugLevelScript
, "setting animation code of %s to %s", _debugInfo
, +anim
);
32 _baseOffset
= anim
.offset();
34 _debugInvalid
= false;
35 _attentionNeeded
= false;
40 _baseOffset
= _offset
= 0;
43 void Actor::callMe(const CodePointer
&code
) {
44 _callBacks
.push(code
);
47 void Actor::tellMe(const CodePointer
&code
, uint16 timeout
) {
48 _roomCallbacks
.push_back(RoomCallback(timeout
, code
));
51 bool Actor::isFine() const {
52 return _room
== Log
.currentRoom() &&
53 _base
&& !_attentionNeeded
;
56 void Actor::setFrame(uint16 frame
) {
58 Frame
f(Log
.room()->getFrame(frame
));
59 _position
.x
= f
.left();
60 _position
.y
= f
.top();
63 void Actor::setRoom(uint16 r
, uint16 frame
, uint16 next_frame
) {
67 _nextFrame
= next_frame
;
70 _offset
= _puppeteer
.mainCodeOffset();
73 Animation::Status
Actor::tick() {
77 if (_debug
) gDebugLevel
+= 3;
78 s
= Animation::tick();
79 if (_debug
) gDebugLevel
-= 3;
85 void Actor::toggleDebug() {
89 void Actor::readHeader(const byte
*code
) {
90 _interval
= code
[kOffsetInterval
];
91 _ticksLeft
= READ_LE_UINT16(code
+ kOffsetTicksLeft
);
93 _position
= Common::Point(READ_LE_UINT16(code
+ kOffsetLeft
), READ_LE_UINT16(code
+ kOffsetTop
));
94 uint16 baseOff
= READ_LE_UINT16(code
+ kOffsetCode
);
96 _offset
= READ_LE_UINT16(code
+ kOffsetOffset
);
97 uint16 sprite
= READ_LE_UINT16(code
+ kOffsetMainSprite
);
98 _room
= READ_LE_UINT16(code
+ kOffsetRoom
);
100 debugC(3, kDebugLevelFiles
, "loading %s: interv %d ticks %d z%d pos%d:%d code %d offset %d sprite %d room %d", _debugInfo
, _interval
, _ticksLeft
, _zIndex
, _position
.x
, _position
.y
, baseOff
, _offset
, sprite
, _room
);
102 if (sprite
!= 0xffff)
103 setMainSprite(sprite
);
106 void Actor::callBacks() {
108 while (!_callBacks
.empty())
109 Log
.runLater(_callBacks
.pop());
111 foreach (RoomCallback
, _roomCallbacks
) {
112 if (_room
== Log
.currentRoom() || !it
->timeout
) {
113 Log
.runLater(it
->callback
);
114 _roomCallbacks
.erase(it
);
120 template <int opcode
>
121 Animation::Status
Actor::opcodeHandler(){
122 return Animation::opcodeHandler
<opcode
>();
126 void Actor::init_opcodes() {
127 _handlers
[N
] = &Innocent::Actor::opcodeHandler
<N
>;
132 void Actor::init_opcodes
<-1>() {}
134 Animation::Status
Actor::op(byte opcode
) {
135 return (this->*_handlers
[opcode
])();
138 #define OPCODE(n) template<> Animation::Status Actor::opcodeHandler<n>()
141 uint16 off
= shift();
143 debugC(1, kDebugLevelAnimation
, "actor opcode 0x14: jump to 0x%04x if I'm speaking STUB", off
);
145 // also, some check for non-protagonists
151 debugC(1, kDebugLevelAnimation
, "actor opcode 0x15: look at cursor direction if its mode is 'See' STUB");
157 byte val
= embeddedByte();
158 uint16 off
= shift();
160 debugC(1, kDebugLevelAnimation
, "actor opcode 0x16: if look direction is %d then jump to 0x%04x STUB", val
, off
);
167 byte val
= embeddedByte();
168 uint16 off
= shift();
170 debugC(3, kDebugLevelAnimation
, "actor opcode 0x17: if facing (currently %d) is %d then change code to 0x%04x", _dir63
, val
, off
);
173 _base
= _base
- _baseOffset
+ off
;
182 uint16 val
= shift();
184 debugC(3, kDebugLevelAnimation
, "actor opcode 0x18: set next animator to %x", val
);
191 byte dir
= embeddedByte();
193 debugC(3, kDebugLevelAnimation
, "actor opcode 0x23: face %d", dir
);
201 byte dir
= embeddedByte();
203 debugC(3, kDebugLevelAnimation
, "actor opcode 0x23: set attention needed flag to %d", dir
);
204 _attentionNeeded
= true;
209 } // end of namespace