0x9c
[scummvm-innocent.git] / engines / innocent / actor.cpp
blobcf7411c3a606fadf0dce884aa38a1da1bf87cef7
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"
10 namespace Innocent {
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);
17 readHeader(header);
18 _dir63 = 0;
19 _frame = 0;
20 _room = 0xffff;
21 _debug = false;
22 _attentionNeeded = false;
24 Engine::instance().logic()->addAnimation(this);
26 init_opcodes<37>();
29 void Actor::setAnimation(const CodePointer &anim) {
30 debugC(3, kDebugLevelScript, "setting animation code of %s to %s", _debugInfo, +anim);
31 _base = anim.code();
32 _baseOffset = anim.offset();
33 _offset = 0;
34 _debugInvalid = false;
35 _attentionNeeded = false;
38 void Actor::hide() {
39 _base = 0;
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) {
57 _frame = 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) {
64 _room = r;
65 unless (next_frame)
66 next_frame = frame;
67 _nextFrame = next_frame;
68 setFrame(frame);
70 _offset = _puppeteer.mainCodeOffset();
73 Animation::Status Actor::tick() {
74 callBacks();
75 if (isFine()) {
76 Animation::Status s;
77 if (_debug) gDebugLevel += 3;
78 s = Animation::tick();
79 if (_debug) gDebugLevel -= 3;
80 return s;
81 } else
82 return kOk;
85 void Actor::toggleDebug() {
86 _debug = !_debug;
89 void Actor::readHeader(const byte *code) {
90 _interval = code[kOffsetInterval];
91 _ticksLeft = READ_LE_UINT16(code + kOffsetTicksLeft);
92 _zIndex = 0;
93 _position = Common::Point(READ_LE_UINT16(code + kOffsetLeft), READ_LE_UINT16(code + kOffsetTop));
94 uint16 baseOff = READ_LE_UINT16(code + kOffsetCode);
95 _base += baseOff;
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() {
107 unless (isFine())
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);
115 } else
116 it->timeout--;
120 template <int opcode>
121 Animation::Status Actor::opcodeHandler(){
122 return Animation::opcodeHandler<opcode>();
125 template<int N>
126 void Actor::init_opcodes() {
127 _handlers[N] = &Innocent::Actor::opcodeHandler<N>;
128 init_opcodes<N-1>();
131 template<>
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>()
140 OPCODE(0x14) {
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
147 return kOk;
150 OPCODE(0x15) {
151 debugC(1, kDebugLevelAnimation, "actor opcode 0x15: look at cursor direction if its mode is 'See' STUB");
153 return kOk;
156 OPCODE(0x16) {
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);
161 error("stub");
163 return kOk;
166 OPCODE(0x17) {
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);
172 if (val == _dir63) {
173 _base = _base - _baseOffset + off;
174 _baseOffset = off;
175 _offset = 0;
178 return kOk;
181 OPCODE(0x18) {
182 uint16 val = shift();
184 debugC(3, kDebugLevelAnimation, "actor opcode 0x18: set next animator to %x", val);
185 _nextAnimator = val;
187 return kOk;
190 OPCODE(0x23) {
191 byte dir = embeddedByte();
193 debugC(3, kDebugLevelAnimation, "actor opcode 0x23: face %d", dir);
195 _dir63 = dir;
197 return kOk;
200 OPCODE(0x24) {
201 byte dir = embeddedByte();
203 debugC(3, kDebugLevelAnimation, "actor opcode 0x23: set attention needed flag to %d", dir);
204 _attentionNeeded = true;
206 return kOk;
209 } // end of namespace