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 #include "ultima/ultima8/world/actors/grant_peace_process.h"
24 #include "ultima/ultima8/world/world.h"
25 #include "ultima/ultima8/world/current_map.h"
26 #include "ultima/ultima8/gumps/target_gump.h"
27 #include "ultima/ultima8/graphics/palette_fader_process.h"
28 #include "ultima/ultima8/usecode/uc_list.h"
29 #include "ultima/ultima8/world/loop_script.h"
30 #include "ultima/ultima8/kernel/kernel.h"
31 #include "ultima/ultima8/gumps/gump_notify_process.h"
32 #include "ultima/ultima8/world/actors/main_actor.h"
33 #include "ultima/ultima8/world/sprite_process.h"
34 #include "ultima/ultima8/audio/audio_process.h"
35 #include "ultima/ultima8/world/get_object.h"
36
37 namespace Ultima {
38 namespace Ultima8 {
39
DEFINE_RUNTIME_CLASSTYPE_CODE(GrantPeaceProcess)40 DEFINE_RUNTIME_CLASSTYPE_CODE(GrantPeaceProcess)
41
42 GrantPeaceProcess::GrantPeaceProcess() : Process(), _haveTarget(false) {
43 }
44
GrantPeaceProcess(Actor * caster)45 GrantPeaceProcess::GrantPeaceProcess(Actor *caster) {
46 assert(caster);
47 _itemNum = caster->getObjId();
48
49 _type = 0x21d; // CONSTANT !
50
51 _haveTarget = false;
52 }
53
run()54 void GrantPeaceProcess::run() {
55 Actor *caster = getActor(_itemNum);
56 if (!caster) {
57 terminate();
58 return;
59 }
60
61 if (!_haveTarget) {
62 TargetGump *targetgump = new TargetGump(0, 0);
63 targetgump->InitGump(0);
64
65 waitFor(targetgump->GetNotifyProcess()->getPid());
66
67 _haveTarget = true;
68
69 return;
70 }
71
72 // get target _result
73 ObjId targetid = static_cast<ObjId>(_result);
74 Actor *target = getActor(targetid);
75
76 if (targetid == 1 || !target) {
77 // targeting the avatar, no target or not an Actor
78 terminate();
79 return;
80 }
81
82 bool hit = false;
83
84 if (target->getDefenseType() & WeaponInfo::DMG_UNDEAD) {
85 // undead
86
87 // first see if we're near Khumash-Gor
88 CurrentMap *currentmap = World::get_instance()->getCurrentMap();
89 UCList KGlist(2);
90 LOOPSCRIPT(script, LS_SHAPE_EQUAL(289));
91 currentmap->areaSearch(&KGlist, script, sizeof(script),
92 caster, 2048, false);
93 bool khumash = (KGlist.getSize() > 0);
94
95 // then find all the undead in the area
96 UCList itemlist(2);
97 LOOPSCRIPT(script2, LS_TOKEN_TRUE);
98 currentmap->areaSearch(&itemlist, script2, sizeof(script2),
99 caster, 768, false);
100
101 for (unsigned int i = 0; i < itemlist.getSize(); ++i) {
102 Actor *t = getActor(itemlist.getuint16(i));
103 if (!t) continue;
104 if (t == caster) continue;
105
106 if (t->isDead()) continue;
107
108 // undead?
109 if (t->getDefenseType() & WeaponInfo::DMG_UNDEAD) {
110 t->receiveHit(_itemNum, dir_current, target->getHP(),
111 (WeaponInfo::DMG_MAGIC |
112 WeaponInfo::DMG_PIERCE |
113 WeaponInfo::DMG_FIRE));
114 hit = true;
115
116 if (t->getShape() == 411 && khumash) { // CONSTANT!
117 int32 tx, ty, tz;
118 t->getLocation(tx, ty, tz);
119
120 // CONSTANT! (shape 480, frame 0-9, repeat 1, delay 1)
121 Process *sp = new SpriteProcess(480, 0, 9, 1, 1, tx, ty, tz);
122 Kernel::get_instance()->addProcess(sp);
123
124 Item *throne = getItem(KGlist.getuint16(0));
125 if (throne) {
126 throne->setFrame(1); // CONSTANT!
127 }
128 }
129
130 #if 0
131 // FIXME: this seems to screw up the death animation; why?
132
133 int dir = caster->getDirToItemCentre(*t);
134
135 t->hurl(((getRandom() % 5) + 5) * x_fact[dir],
136 ((getRandom() % 5) + 5) * y_fact[dir],
137 ((getRandom() % 5) + 5),
138 4);
139 #endif
140 }
141
142 }
143
144 } else {
145 // not undead
146
147 if (!target->hasActorFlags(Actor::ACT_DEAD |
148 Actor::ACT_IMMORTAL |
149 Actor::ACT_INVINCIBLE)) {
150 if (getRandom() % 10 == 0) {
151 target->receiveHit(_itemNum, dir_current, target->getHP(),
152 (WeaponInfo::DMG_MAGIC |
153 WeaponInfo::DMG_PIERCE |
154 WeaponInfo::DMG_FIRE));
155 hit = true;
156 }
157 }
158
159 }
160
161
162 if (hit) {
163 // lightning
164
165 // calling intrinsic...
166 PaletteFaderProcess::I_lightningBolt(0, 0);
167 int sfx;
168 switch (getRandom() % 3) {
169 case 0:
170 sfx = 91;
171 break;
172 case 1:
173 sfx = 94;
174 break;
175 default:
176 sfx = 96;
177 break;
178 }
179
180 AudioProcess *audioproc = AudioProcess::get_instance();
181 if (audioproc) audioproc->playSFX(sfx, 0x60, 1, 0); //constants!!
182 }
183
184
185 // done
186 terminate();
187 }
188
I_castGrantPeace(const uint8 * args,unsigned int)189 uint32 GrantPeaceProcess::I_castGrantPeace(const uint8 *args,
190 unsigned int /*argsize*/) {
191 MainActor *avatar = getMainActor();
192
193 GrantPeaceProcess *gpp = new GrantPeaceProcess(avatar);
194 Kernel::get_instance()->addProcess(gpp);
195
196 // start casting
197 ProcId anim1 = avatar->doAnim(Animation::cast1, dir_current);
198
199 // cast
200 ProcId anim2 = avatar->doAnim(Animation::cast3, dir_current);
201 Process *anim2p = Kernel::get_instance()->getProcess(anim2);
202
203 // end casting
204 ProcId anim3 = avatar->doAnim(Animation::cast2, dir_current);
205 Process *anim3p = Kernel::get_instance()->getProcess(anim3);
206
207 anim2p->waitFor(anim1);
208 anim3p->waitFor(anim2);
209 gpp->waitFor(anim2);
210
211 return 0;
212 }
213
saveData(Common::WriteStream * ws)214 void GrantPeaceProcess::saveData(Common::WriteStream *ws) {
215 Process::saveData(ws);
216
217 uint8 ht = _haveTarget ? 1 : 0;
218 ws->writeByte(ht);
219 }
220
loadData(Common::ReadStream * rs,uint32 version)221 bool GrantPeaceProcess::loadData(Common::ReadStream *rs, uint32 version) {
222 if (!Process::loadData(rs, version)) return false;
223
224 _haveTarget = (rs->readByte() != 0);
225
226 return true;
227 }
228
229 } // End of namespace Ultima8
230 } // End of namespace Ultima
231