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