1 /**
2 * @file towners.cpp
3 *
4 * Implementation of functionality for loading and spawning towners.
5 */
6 #include "all.h"
7
8 DEVILUTION_BEGIN_NAMESPACE
9
10 BOOL storeflag;
11 int sgnCowMsg;
12 int numtowners;
13 DWORD sgdwCowClicks;
14 BYTE *pCowCels;
15 TownerStruct towner[NUM_TOWNERS];
16
17 /**
18 * Maps from active cow sound effect index and player class to sound
19 * effect ID for interacting with cows in Tristram.
20 *
21 * ref: enum _sfx_id
22 * ref: enum plr_class
23 */
24 const int snSFX[3][NUM_CLASSES] = {
25 { PS_WARR52, PS_ROGUE52, PS_MAGE52, PS_MONK52, PS_ROGUE52, PS_WARR52 }, // BUGFIX: add warrior sounds for barbarian instead of 0 - walk sound (fixed)
26 { PS_WARR49, PS_ROGUE49, PS_MAGE49, PS_MONK49, PS_ROGUE49, PS_WARR49 },
27 { PS_WARR50, PS_ROGUE50, PS_MAGE50, PS_MONK50, PS_ROGUE50, PS_WARR50 },
28 };
29
30 /* data */
31 /** Specifies the animation frame sequence of a given NPC. */
32 char AnimOrder[6][148] = {
33 { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
34 14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
35 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
36 14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
37 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
38 14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
39 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
40 14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
41 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
42 14, 13, 12, 11, 10, 9, 8, 7, 6, 5,
43 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
44 15, 5, 1, 1, 1, 1, 1, 1, 1, 1,
45 1, 1, 1, 1, 1, 1, 1, 2, 3, 4,
46 -1 },
47 { 1, 2, 3, 3, 2, 1, 20, 19, 19, 20,
48 1, 2, 3, 3, 2, 1, 20, 19, 19, 20,
49 1, 2, 3, 3, 2, 1, 20, 19, 19, 20,
50 1, 2, 3, 3, 2, 1, 20, 19, 19, 20,
51 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
52 11, 12, 13, 14, 15, 16, 15, 14, 13, 12,
53 11, 10, 9, 8, 7, 6, 5, 4, 5, 6,
54 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
55 15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
56 5, 4, 5, 6, 7, 8, 9, 10, 11, 12,
57 13, 14, 15, 16, 17, 18, 19, 20, -1 },
58 { 1, 1, 25, 25, 24, 23, 22, 21, 20, 19,
59 18, 17, 16, 15, 16, 17, 18, 19, 20, 21,
60 22, 23, 24, 25, 25, 25, 1, 1, 1, 25,
61 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
62 11, 12, 13, 14, 15, 14, 13, 12, 11, 10,
63 9, 8, 7, 6, 5, 4, 3, 2, 1, -1 },
64 { 1, 2, 3, 3, 2, 1, 16, 15, 14, 14,
65 16, 1, 2, 3, 3, 2, 1, 16, 15, 14,
66 14, 15, 16, 1, 2, 3, 3, 2, 1, 16,
67 15, 14, 14, 15, 16, 1, 2, 3, 3, 2,
68 1, 16, 15, 14, 14, 15, 16, 1, 2, 3,
69 3, 2, 1, 16, 15, 14, 14, 15, 16, 1,
70 2, 3, 3, 2, 1, 16, 15, 14, 14, 15,
71 16, 1, 2, 3, 3, 2, 1, 16, 15, 14,
72 14, 15, 16, 1, 2, 3, 2, 1, 16, 15,
73 14, 14, 15, 16, 1, 2, 3, 4, 5, 6,
74 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
75 -1 },
76 { 1, 1, 1, 2, 3, 4, 5, 6, 7, 8,
77 9, 10, 11, 11, 11, 11, 12, 13, 14, 15,
78 16, 17, 18, 18, 1, 1, 1, 18, 17, 16,
79 15, 14, 13, 12, 11, 10, 11, 12, 13, 14,
80 15, 16, 17, 18, 1, 2, 3, 4, 5, 5,
81 5, 4, 3, 2, -1 },
82 { 4, 4, 4, 5, 6, 6, 6, 5, 4, 15,
83 14, 13, 13, 13, 14, 15, 4, 5, 6, 6,
84 6, 5, 4, 4, 4, 5, 6, 6, 6, 5,
85 4, 15, 14, 13, 13, 13, 14, 15, 4, 5,
86 6, 6, 6, 5, 4, 4, 4, 5, 6, 6,
87 6, 5, 4, 15, 14, 13, 13, 13, 14, 15,
88 4, 5, 6, 6, 6, 5, 4, 3, 2, 1,
89 19, 18, 19, 1, 2, 1, 19, 18, 19, 1,
90 2, 1, 2, 3, 4, 5, 6, 7, 8, 9,
91 10, 11, 12, 13, 14, 15, 15, 15, 14, 13,
92 13, 13, 13, 14, 15, 15, 15, 14, 13, 12,
93 12, 12, 11, 10, 10, 10, 9, 8, 9, 10,
94 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
95 1, 2, 1, 19, 18, 19, 1, 2, 1, 2,
96 3, -1 }
97 };
98 /** Specifies the start X-coordinates of the cows in Tristram. */
99 int TownCowX[] = { 58, 56, 59 };
100 /** Specifies the start Y-coordinates of the cows in Tristram. */
101 int TownCowY[] = { 16, 14, 20 };
102 /** Specifies the start directions of the cows in Tristram. */
103 int TownCowDir[] = { DIR_SW, DIR_NW, DIR_N };
104 /** Maps from direction to X-coordinate delta, which is used when
105 * placing cows in Tristram. A single cow may require space of up
106 * to three tiles when being placed on the map.
107 */
108 int cowoffx[8] = { -1, 0, -1, -1, -1, 0, -1, -1 };
109 /** Maps from direction to Y-coordinate delta, which is used when
110 * placing cows in Tristram. A single cow may require space of up
111 * to three tiles when being placed on the map.
112 */
113 int cowoffy[8] = { -1, -1, -1, 0, -1, -1, -1, 0 };
114 /** Contains the data related to quest gossip for each towner ID. */
115 _speech_id Qtalklist[NUM_TOWNER_TYPES][MAXQUESTS] = {
116 // clang-format off
117 // Q_ROCK, Q_MUSHROOM, Q_GARBUD, Q_ZHAR, Q_VEIL, Q_DIABLO, Q_BUTCHER, Q_LTBANNER, Q_BLIND, Q_BLOOD, Q_ANVIL, Q_WARLORD, Q_SKELKING, Q_PWATER, Q_SCHAMB, Q_BETRAYER, Q_GRAVE, Q_FARMER, Q_GIRL, Q_TRADER, Q_DEFILER, Q_NAKRUL, Q_CORNSTN, Q_JERSEY
118 /*TOWN_SMITH*/ { TEXT_INFRA6, TEXT_MUSH6, TEXT_NONE, TEXT_NONE, TEXT_VEIL5, TEXT_NONE, TEXT_BUTCH5, TEXT_BANNER6, TEXT_BLIND5, TEXT_BLOOD5, TEXT_ANVIL6, TEXT_WARLRD5, TEXT_KING7, TEXT_POISON7, TEXT_BONE5, TEXT_VILE9, TEXT_GRAVE2, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
119 /*TOWN_HEALER*/ { TEXT_INFRA3, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_VEIL3, TEXT_NONE, TEXT_BUTCH3, TEXT_BANNER4, TEXT_BLIND3, TEXT_BLOOD3, TEXT_ANVIL3, TEXT_WARLRD3, TEXT_KING5, TEXT_POISON4, TEXT_BONE3, TEXT_VILE7, TEXT_GRAVE3, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
120 /*TOWN_DEADGUY*/ { TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
121 /*TOWN_TAVERN*/ { TEXT_INFRA2, TEXT_MUSH2, TEXT_NONE, TEXT_NONE, TEXT_VEIL2, TEXT_NONE, TEXT_BUTCH2, TEXT_NONE, TEXT_BLIND2, TEXT_BLOOD2, TEXT_ANVIL2, TEXT_WARLRD2, TEXT_KING3, TEXT_POISON2, TEXT_BONE2, TEXT_VILE4, TEXT_GRAVE5, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
122 /*TOWN_STORY*/ { TEXT_INFRA1, TEXT_MUSH1, TEXT_NONE, TEXT_NONE, TEXT_VEIL1, TEXT_VILE3, TEXT_BUTCH1, TEXT_BANNER1, TEXT_BLIND1, TEXT_BLOOD1, TEXT_ANVIL1, TEXT_WARLRD1, TEXT_KING1, TEXT_POISON1, TEXT_BONE1, TEXT_VILE2, TEXT_GRAVE6, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
123 /*TOWN_DRUNK*/ { TEXT_INFRA8, TEXT_MUSH7, TEXT_NONE, TEXT_NONE, TEXT_VEIL6, TEXT_NONE, TEXT_BUTCH6, TEXT_BANNER7, TEXT_BLIND6, TEXT_BLOOD6, TEXT_ANVIL8, TEXT_WARLRD6, TEXT_KING8, TEXT_POISON8, TEXT_BONE6, TEXT_VILE10, TEXT_GRAVE7, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
124 /*TOWN_WITCH*/ { TEXT_INFRA9, TEXT_MUSH9, TEXT_NONE, TEXT_NONE, TEXT_VEIL7, TEXT_NONE, TEXT_BUTCH7, TEXT_BANNER8, TEXT_BLIND7, TEXT_BLOOD7, TEXT_ANVIL9, TEXT_WARLRD7, TEXT_KING9, TEXT_POISON9, TEXT_BONE7, TEXT_VILE11, TEXT_GRAVE1, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
125 /*TOWN_BMAID*/ { TEXT_INFRA4, TEXT_MUSH5, TEXT_NONE, TEXT_NONE, TEXT_VEIL4, TEXT_NONE, TEXT_BUTCH4, TEXT_BANNER5, TEXT_BLIND4, TEXT_BLOOD4, TEXT_ANVIL4, TEXT_WARLRD4, TEXT_KING6, TEXT_POISON6, TEXT_BONE4, TEXT_VILE8, TEXT_GRAVE8, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
126 /*TOWN_PEGBOY*/ { TEXT_INFRA10, TEXT_MUSH13, TEXT_NONE, TEXT_NONE, TEXT_VEIL8, TEXT_NONE, TEXT_BUTCH8, TEXT_BANNER9, TEXT_BLIND8, TEXT_BLOOD8, TEXT_ANVIL10, TEXT_WARLRD8, TEXT_KING10, TEXT_POISON10, TEXT_BONE8, TEXT_VILE12, TEXT_GRAVE9, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
127 /*TOWN_COW*/ { TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
128 /*TOWN_FARMER*/ { TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
129 /*TOWN_GIRL*/ { TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
130 /*TOWN_COWFARM*/ { TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE, TEXT_NONE },
131 // clang-format on
132 };
133 /** Specifies the active sound effect ID for interacting with cows. */
134 int CowPlaying = -1;
135
CowSFX(int pnum)136 static void CowSFX(int pnum)
137 {
138 if (CowPlaying != -1 && effect_is_playing(CowPlaying))
139 return;
140
141 sgdwCowClicks++;
142
143 if (gbIsSpawn) {
144 if (sgdwCowClicks == 4) {
145 sgdwCowClicks = 0;
146 CowPlaying = TSFX_COW2;
147 } else {
148 CowPlaying = TSFX_COW1;
149 }
150 } else {
151 if (sgdwCowClicks >= 8) {
152 PlaySfxLoc(TSFX_COW1, plr[pnum]._px, plr[pnum]._py + 5);
153 sgdwCowClicks = 4;
154 CowPlaying = snSFX[sgnCowMsg][plr[pnum]._pClass]; /* snSFX is local */
155 sgnCowMsg++;
156 if (sgnCowMsg >= 3)
157 sgnCowMsg = 0;
158 } else {
159 CowPlaying = sgdwCowClicks == 4 ? TSFX_COW2 : TSFX_COW1;
160 }
161 }
162
163 PlaySfxLoc(CowPlaying, plr[pnum]._px, plr[pnum]._py);
164 }
165
GetActiveTowner(int t)166 int GetActiveTowner(int t)
167 {
168 int i;
169
170 for (i = 0; i < numtowners; i++) {
171 if (towner[i]._ttype == t)
172 return i;
173 }
174
175 return -1;
176 }
177
SetTownerGPtrs(BYTE * pData,BYTE ** pAnim)178 void SetTownerGPtrs(BYTE *pData, BYTE **pAnim)
179 {
180 int i;
181 DWORD *pFrameTable;
182
183 pFrameTable = (DWORD *)pData;
184
185 for (i = 0; i < 8; i++) {
186 pAnim[i] = CelGetFrameStart(pData, i);
187 }
188 }
189
NewTownerAnim(int tnum,BYTE * pAnim,int numFrames,int Delay)190 void NewTownerAnim(int tnum, BYTE *pAnim, int numFrames, int Delay)
191 {
192 towner[tnum]._tAnimData = pAnim;
193 towner[tnum]._tAnimLen = numFrames;
194 towner[tnum]._tAnimFrame = 1;
195 towner[tnum]._tAnimCnt = 0;
196 towner[tnum]._tAnimDelay = Delay;
197 }
198
InitTownerInfo(int i,int w,int sel,int t,int x,int y,int ao,int tp)199 void InitTownerInfo(int i, int w, int sel, int t, int x, int y, int ao, int tp)
200 {
201 memset(&towner[i], 0, sizeof(TownerStruct));
202 towner[i]._tSelFlag = sel;
203 towner[i]._tAnimWidth = w;
204 towner[i]._tAnimWidth2 = (w - 64) >> 1;
205 towner[i]._tMsgSaid = FALSE;
206 towner[i]._ttype = t;
207 towner[i]._tx = x;
208 towner[i]._ty = y;
209 dMonster[x][y] = i + 1;
210 towner[i]._tAnimOrder = ao;
211 towner[i]._tTenPer = tp;
212 towner[i]._tSeed = AdvanceRndSeed();
213 }
214
InitQstSnds(int id,_talker_id type)215 void InitQstSnds(int id, _talker_id type)
216 {
217 for (int i = 0; i < MAXQUESTS; i++) {
218 towner[id].qsts[i]._qsttype = quests[i]._qtype;
219 towner[id].qsts[i]._qstmsg = Qtalklist[type][i];
220 towner[id].qsts[i]._qstmsgact = Qtalklist[type][i] != TEXT_NONE;
221 }
222 }
223
224 /**
225 * @brief Load Griswold into the game
226 */
InitSmith()227 void InitSmith()
228 {
229 int i;
230
231 InitTownerInfo(numtowners, 96, TRUE, TOWN_SMITH, 62, 63, 0, 10);
232 InitQstSnds(numtowners, TOWN_SMITH);
233 towner[numtowners]._tNData = LoadFileInMem("Towners\\Smith\\SmithN.CEL", NULL);
234 for (i = 0; i < 8; i++) {
235 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
236 }
237 towner[numtowners]._tNFrames = 16;
238 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_SW], towner[numtowners]._tNFrames, 3);
239 strcpy(towner[numtowners]._tName, "Griswold the Blacksmith");
240 numtowners++;
241 }
242
InitBarOwner()243 void InitBarOwner()
244 {
245 InitTownerInfo(numtowners, 96, TRUE, TOWN_TAVERN, 55, 62, 3, 10);
246 InitQstSnds(numtowners, TOWN_TAVERN);
247 towner[numtowners]._tNData = LoadFileInMem("Towners\\TwnF\\TwnFN.CEL", NULL);
248 for (int i = 0; i < 8; i++) {
249 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
250 }
251 towner[numtowners]._tNFrames = 16;
252 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_SW], towner[numtowners]._tNFrames, 3);
253 strcpy(towner[numtowners]._tName, "Ogden the Tavern owner");
254 numtowners++;
255 }
256
InitTownDead()257 void InitTownDead()
258 {
259 int i;
260
261 InitTownerInfo(numtowners, 96, TRUE, TOWN_DEADGUY, 24, 32, -1, 10);
262 InitQstSnds(numtowners, TOWN_DEADGUY);
263 towner[numtowners]._tNData = LoadFileInMem("Towners\\Butch\\Deadguy.CEL", NULL);
264 for (i = 0; i < 8; i++) {
265 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
266 }
267 towner[numtowners]._tNFrames = 8;
268 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_N], towner[numtowners]._tNFrames, 6);
269 strcpy(towner[numtowners]._tName, "Wounded Townsman");
270 numtowners++;
271 }
272
InitWitch()273 void InitWitch()
274 {
275 int i;
276
277 InitTownerInfo(numtowners, 96, TRUE, TOWN_WITCH, 80, 20, 5, 10);
278 InitQstSnds(numtowners, TOWN_WITCH);
279 towner[numtowners]._tNData = LoadFileInMem("Towners\\TownWmn1\\Witch.CEL", NULL);
280 for (i = 0; i < 8; i++) {
281 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
282 }
283 towner[numtowners]._tNFrames = 19;
284 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 6);
285 strcpy(towner[numtowners]._tName, "Adria the Witch");
286 numtowners++;
287 }
288
InitBarmaid()289 void InitBarmaid()
290 {
291 int i;
292
293 InitTownerInfo(numtowners, 96, TRUE, TOWN_BMAID, 43, 66, -1, 10);
294 InitQstSnds(numtowners, TOWN_BMAID);
295 towner[numtowners]._tNData = LoadFileInMem("Towners\\TownWmn1\\WmnN.CEL", NULL);
296 for (i = 0; i < 8; i++) {
297 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
298 }
299 towner[numtowners]._tNFrames = 18;
300 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 6);
301 strcpy(towner[numtowners]._tName, "Gillian the Barmaid");
302 numtowners++;
303 }
304
InitBoy()305 void InitBoy()
306 {
307 int i;
308
309 InitTownerInfo(numtowners, 96, TRUE, TOWN_PEGBOY, 11, 53, -1, 10);
310 InitQstSnds(numtowners, TOWN_PEGBOY);
311 towner[numtowners]._tNData = LoadFileInMem("Towners\\TownBoy\\PegKid1.CEL", NULL);
312 for (i = 0; i < 8; i++) {
313 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
314 }
315 towner[numtowners]._tNFrames = 20;
316 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 6);
317 strcpy(towner[numtowners]._tName, "Wirt the Peg-legged boy");
318 numtowners++;
319 }
320
InitHealer()321 void InitHealer()
322 {
323 int i;
324
325 InitTownerInfo(numtowners, 96, TRUE, TOWN_HEALER, 55, 79, 1, 10);
326 InitQstSnds(numtowners, TOWN_HEALER);
327 towner[numtowners]._tNData = LoadFileInMem("Towners\\Healer\\Healer.CEL", NULL);
328 for (i = 0; i < 8; i++) {
329 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
330 }
331 towner[numtowners]._tNFrames = 20;
332 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_SE], towner[numtowners]._tNFrames, 6);
333 strcpy(towner[numtowners]._tName, "Pepin the Healer");
334 numtowners++;
335 }
336
InitTeller()337 void InitTeller()
338 {
339 int i;
340
341 InitTownerInfo(numtowners, 96, TRUE, TOWN_STORY, 62, 71, 2, 10);
342 InitQstSnds(numtowners, TOWN_STORY);
343 towner[numtowners]._tNData = LoadFileInMem("Towners\\Strytell\\Strytell.CEL", NULL);
344 for (i = 0; i < 8; i++) {
345 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
346 }
347 towner[numtowners]._tNFrames = 25;
348 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 3);
349 strcpy(towner[numtowners]._tName, "Cain the Elder");
350 numtowners++;
351 }
352
InitDrunk()353 void InitDrunk()
354 {
355 int i;
356
357 InitTownerInfo(numtowners, 96, TRUE, TOWN_DRUNK, 71, 84, 4, 10);
358 InitQstSnds(numtowners, TOWN_DRUNK);
359 towner[numtowners]._tNData = LoadFileInMem("Towners\\Drunk\\TwnDrunk.CEL", NULL);
360 for (i = 0; i < 8; i++) {
361 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
362 }
363 towner[numtowners]._tNFrames = 18;
364 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 3);
365 strcpy(towner[numtowners]._tName, "Farnham the Drunk");
366 numtowners++;
367 }
368
InitCows()369 void InitCows()
370 {
371 int i, dir;
372 int x, y, xo, yo;
373
374 //if ( pCowCels )
375 // assertion_failed(__LINE__, __FILE__, "! pCowCels");
376 pCowCels = LoadFileInMem("Towners\\Animals\\Cow.CEL", NULL);
377 for (i = 0; i < 3; i++) {
378 x = TownCowX[i];
379 y = TownCowY[i];
380 dir = TownCowDir[i];
381 InitTownerInfo(numtowners, 128, FALSE, TOWN_COW, x, y, -1, 10);
382 towner[numtowners]._tNData = pCowCels;
383 SetTownerGPtrs(towner[numtowners]._tNData, towner[numtowners]._tNAnim);
384 towner[numtowners]._tNFrames = 12;
385 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[dir], towner[numtowners]._tNFrames, 3);
386 towner[numtowners]._tAnimFrame = random_(0, 11) + 1;
387 towner[numtowners]._tSelFlag = TRUE;
388 strcpy(towner[numtowners]._tName, "Cow");
389
390 xo = x + cowoffx[dir];
391 yo = y + cowoffy[dir];
392 if (dMonster[x][yo] == 0)
393 dMonster[x][yo] = -(numtowners + 1);
394 if (dMonster[xo][y] == 0)
395 dMonster[xo][y] = -(numtowners + 1);
396 if (dMonster[xo][yo] == 0)
397 dMonster[xo][yo] = -(numtowners + 1);
398
399 numtowners++;
400 }
401 }
402
InitFarmer()403 void InitFarmer()
404 {
405 int i;
406
407 InitTownerInfo(numtowners, 96, 1, TOWN_FARMER, 62, 16, -1, 10);
408 InitQstSnds(numtowners, TOWN_FARMER);
409 towner[numtowners]._tNData = LoadFileInMem("Towners\\Farmer\\Farmrn2.CEL", NULL);
410 for (i = 0; i < 8; i++) {
411 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
412 }
413 towner[numtowners]._tNFrames = 15;
414 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 3);
415 strcpy(towner[numtowners]._tName, "Lester the farmer");
416 numtowners++;
417 }
418
InitCowFarmer()419 void InitCowFarmer()
420 {
421 int i;
422
423 InitTownerInfo(numtowners, 96, 1, TOWN_COWFARM, 61, 22, -1, 10);
424 InitQstSnds(numtowners, TOWN_COWFARM);
425 if (quests[Q_JERSEY]._qactive != 3) {
426 towner[numtowners]._tNData = LoadFileInMem("Towners\\Farmer\\cfrmrn2.CEL", NULL);
427 } else {
428 towner[numtowners]._tNData = LoadFileInMem("Towners\\Farmer\\mfrmrn2.CEL", NULL);
429 }
430 for (i = 0; i < 8; i++) {
431 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
432 }
433 towner[numtowners]._tNFrames = 15;
434 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_SW], towner[numtowners]._tNFrames, 3);
435 strcpy(towner[numtowners]._tName, "Complete Nut");
436 numtowners++;
437 }
438
InitGirl()439 void InitGirl()
440 {
441 int i;
442
443 InitTownerInfo(numtowners, 96, 1, TOWN_GIRL, 77, 43, -1, 10);
444 InitQstSnds(numtowners, TOWN_GIRL);
445 if (quests[Q_GIRL]._qactive != 3) {
446 towner[numtowners]._tNData = LoadFileInMem("Towners\\Girl\\Girlw1.CEL", NULL);
447 } else {
448 towner[numtowners]._tNData = LoadFileInMem("Towners\\Girl\\Girls1.CEL", NULL);
449 }
450 for (i = 0; i < 8; i++) {
451 towner[numtowners]._tNAnim[i] = towner[numtowners]._tNData;
452 }
453 towner[numtowners]._tNFrames = 20;
454 NewTownerAnim(numtowners, towner[numtowners]._tNAnim[DIR_S], towner[numtowners]._tNFrames, 6);
455 strcpy(towner[numtowners]._tName, "Celia");
456 numtowners++;
457 }
458
InitTowners()459 void InitTowners()
460 {
461 numtowners = 0;
462 InitSmith();
463 InitHealer();
464 if (quests[Q_BUTCHER]._qactive != QUEST_NOTAVAIL && quests[Q_BUTCHER]._qactive != QUEST_DONE)
465 InitTownDead();
466 InitBarOwner();
467 InitTeller();
468 InitDrunk();
469 InitWitch();
470 InitBarmaid();
471 InitBoy();
472 InitCows();
473 if (gbIsHellfire) {
474 if (gbCowQuest) {
475 InitCowFarmer();
476 } else if (quests[Q_FARMER]._qactive != 10) {
477 InitFarmer();
478 }
479 if (gbTheoQuest && plr->_pLvlVisited[17]) {
480 InitGirl();
481 }
482 }
483 }
484
FreeTownerGFX()485 void FreeTownerGFX()
486 {
487 int i;
488
489 for (i = 0; i < NUM_TOWNERS; i++) {
490 if (towner[i]._tNData == pCowCels) {
491 towner[i]._tNData = NULL;
492 } else if (towner[i]._tNData) {
493 MemFreeDbg(towner[i]._tNData);
494 }
495 }
496
497 MemFreeDbg(pCowCels);
498 }
499
TownCtrlMsg(int i)500 void TownCtrlMsg(int i)
501 {
502 int p;
503 int dx, dy;
504
505 if (i == -1)
506 return;
507
508 if (towner[i]._tbtcnt != 0) {
509 p = towner[i]._tVar1;
510 dx = abs(towner[i]._tx - plr[p]._px);
511 dy = abs(towner[i]._ty - plr[p]._py);
512 if (dx >= 2 || dy >= 2) {
513 towner[i]._tbtcnt = 0;
514 qtextflag = FALSE;
515 stream_stop();
516 }
517 }
518 }
519
TownBlackSmith()520 void TownBlackSmith()
521 {
522 int i;
523
524 i = GetActiveTowner(TOWN_SMITH);
525 TownCtrlMsg(i);
526 }
527
TownBarOwner()528 void TownBarOwner()
529 {
530 int i;
531
532 i = GetActiveTowner(TOWN_TAVERN);
533 TownCtrlMsg(i);
534 }
535
TownDead()536 void TownDead()
537 {
538 int tidx;
539
540 tidx = GetActiveTowner(TOWN_DEADGUY);
541 TownCtrlMsg(tidx);
542 if (!qtextflag) {
543 if (quests[Q_BUTCHER]._qactive == QUEST_ACTIVE && !quests[Q_BUTCHER]._qlog) {
544 return;
545 }
546 if (quests[Q_BUTCHER]._qactive != QUEST_INIT) {
547 towner[tidx]._tAnimDelay = 1000;
548 towner[tidx]._tAnimFrame = 1;
549 strcpy(towner[tidx]._tName, "Slain Townsman");
550 }
551 }
552 if (quests[Q_BUTCHER]._qactive != QUEST_INIT)
553 towner[tidx]._tAnimCnt = 0;
554 }
555
TownHealer()556 void TownHealer()
557 {
558 int i;
559
560 i = GetActiveTowner(TOWN_HEALER);
561 TownCtrlMsg(i);
562 }
563
TownStory()564 void TownStory()
565 {
566 int i;
567
568 i = GetActiveTowner(TOWN_STORY);
569 TownCtrlMsg(i);
570 }
571
TownDrunk()572 void TownDrunk()
573 {
574 int i;
575
576 i = GetActiveTowner(TOWN_DRUNK);
577 TownCtrlMsg(i);
578 }
579
TownBoy()580 void TownBoy()
581 {
582 int i;
583
584 i = GetActiveTowner(TOWN_PEGBOY);
585 TownCtrlMsg(i);
586 }
587
TownWitch()588 void TownWitch()
589 {
590 int i;
591
592 i = GetActiveTowner(TOWN_WITCH);
593 TownCtrlMsg(i);
594 }
595
TownBarMaid()596 void TownBarMaid()
597 {
598 int i;
599
600 i = GetActiveTowner(TOWN_BMAID);
601 TownCtrlMsg(i);
602 }
603
TownCow()604 void TownCow()
605 {
606 int i;
607
608 i = GetActiveTowner(TOWN_COW);
609 TownCtrlMsg(i);
610 }
611
TownFarmer()612 void TownFarmer()
613 {
614 int i;
615
616 i = GetActiveTowner(TOWN_FARMER);
617 TownCtrlMsg(i);
618 }
619
TownCowFarmer()620 void TownCowFarmer()
621 {
622 int i;
623
624 i = GetActiveTowner(TOWN_COWFARM);
625 TownCtrlMsg(i);
626 }
627
TownGirl()628 void TownGirl()
629 {
630 int i;
631
632 i = GetActiveTowner(TOWN_GIRL);
633 TownCtrlMsg(i);
634 }
635
ProcessTowners()636 void ProcessTowners()
637 {
638 int i, ao;
639
640 for (i = 0; i < NUM_TOWNERS; i++) {
641 switch (towner[i]._ttype) {
642 case TOWN_SMITH:
643 TownBlackSmith();
644 break;
645 case TOWN_HEALER:
646 TownHealer();
647 break;
648 case TOWN_DEADGUY:
649 TownDead();
650 break;
651 case TOWN_TAVERN:
652 TownBarOwner();
653 break;
654 case TOWN_STORY:
655 TownStory();
656 break;
657 case TOWN_DRUNK:
658 TownDrunk();
659 break;
660 case TOWN_WITCH:
661 TownWitch();
662 break;
663 case TOWN_BMAID:
664 TownBarMaid();
665 break;
666 case TOWN_PEGBOY:
667 TownBoy();
668 break;
669 case TOWN_COW:
670 TownCow();
671 break;
672 case TOWN_FARMER:
673 TownFarmer();
674 break;
675 case TOWN_GIRL:
676 TownGirl();
677 break;
678 case TOWN_COWFARM:
679 TownCowFarmer();
680 break;
681 }
682
683 towner[i]._tAnimCnt++;
684 if (towner[i]._tAnimCnt >= towner[i]._tAnimDelay) {
685 towner[i]._tAnimCnt = 0;
686
687 if (towner[i]._tAnimOrder >= 0) {
688 ao = towner[i]._tAnimOrder;
689 towner[i]._tAnimFrameCnt++;
690 if (AnimOrder[ao][towner[i]._tAnimFrameCnt] == -1)
691 towner[i]._tAnimFrameCnt = 0;
692
693 towner[i]._tAnimFrame = AnimOrder[ao][towner[i]._tAnimFrameCnt];
694 } else {
695 towner[i]._tAnimFrame++;
696 if (towner[i]._tAnimFrame > towner[i]._tAnimLen)
697 towner[i]._tAnimFrame = 1;
698 }
699 }
700 }
701 }
702
PlrHasItem(int pnum,int item,int * i)703 ItemStruct *PlrHasItem(int pnum, int item, int *i)
704 {
705 for (*i = 0; *i < plr[pnum]._pNumInv; (*i)++) {
706 if (plr[pnum].InvList[*i].IDidx == item)
707 return &plr[pnum].InvList[*i];
708 }
709
710 return NULL;
711 }
712
TownerTalk(int first,int t)713 void TownerTalk(int first, int t)
714 {
715 sgdwCowClicks = 0;
716 sgnCowMsg = 0;
717 storeflag = TRUE;
718 InitQTextMsg(first);
719 }
720
TalkToTowner(int p,int t)721 void TalkToTowner(int p, int t)
722 {
723 int i, dx, dy, rv1, rv2, rv3;
724 ItemStruct *Item;
725 int qt, t2;
726
727 dx = abs(plr[p]._px - towner[t]._tx);
728 dy = abs(plr[p]._py - towner[t]._ty);
729 #ifdef _DEBUG
730 if (!debug_mode_key_d)
731 #endif
732 if (dx >= 2 || dy >= 2)
733 return;
734
735 if (qtextflag) {
736 return;
737 }
738
739 towner[t]._tMsgSaid = FALSE;
740
741 if (pcurs >= CURSOR_FIRSTITEM) {
742 return;
743 }
744
745 if (t == GetActiveTowner(TOWN_TAVERN)) {
746 if (!plr[p]._pLvlVisited[0] && !towner[t]._tMsgSaid) {
747 towner[t]._tbtcnt = 150;
748 towner[t]._tVar1 = p;
749 InitQTextMsg(TEXT_INTRO);
750 towner[t]._tMsgSaid = TRUE;
751 }
752 if ((plr[p]._pLvlVisited[2] || plr[p]._pLvlVisited[4]) && quests[Q_SKELKING]._qactive != QUEST_NOTAVAIL) {
753 if (quests[Q_SKELKING]._qactive != QUEST_NOTAVAIL) {
754 if (quests[Q_SKELKING]._qvar2 == 0 && !towner[t]._tMsgSaid) {
755 quests[Q_SKELKING]._qvar2 = 1;
756 quests[Q_SKELKING]._qlog = TRUE;
757 if (quests[Q_SKELKING]._qactive == QUEST_INIT) {
758 quests[Q_SKELKING]._qactive = QUEST_ACTIVE;
759 quests[Q_SKELKING]._qvar1 = 1;
760 }
761 towner[t]._tbtcnt = 150;
762 towner[t]._tVar1 = p;
763 InitQTextMsg(TEXT_KING2);
764 towner[t]._tMsgSaid = TRUE;
765 NetSendCmdQuest(TRUE, Q_SKELKING);
766 }
767 }
768 if (quests[Q_SKELKING]._qactive == QUEST_DONE && quests[Q_SKELKING]._qvar2 == 1 && !towner[t]._tMsgSaid) {
769 quests[Q_SKELKING]._qvar2 = 2;
770 quests[Q_SKELKING]._qvar1 = 2;
771 towner[t]._tbtcnt = 150;
772 towner[t]._tVar1 = p;
773 InitQTextMsg(TEXT_KING4);
774 towner[t]._tMsgSaid = TRUE;
775 NetSendCmdQuest(TRUE, Q_SKELKING);
776 }
777 }
778 if (!gbIsMultiplayer) {
779 if (plr[p]._pLvlVisited[3] && quests[Q_LTBANNER]._qactive != QUEST_NOTAVAIL) {
780 if ((quests[Q_LTBANNER]._qactive == QUEST_INIT || quests[Q_LTBANNER]._qactive == QUEST_ACTIVE) && quests[Q_LTBANNER]._qvar2 == 0 && !towner[t]._tMsgSaid) {
781 quests[Q_LTBANNER]._qvar2 = 1;
782 if (quests[Q_LTBANNER]._qactive == QUEST_INIT) {
783 quests[Q_LTBANNER]._qvar1 = 1;
784 quests[Q_LTBANNER]._qactive = QUEST_ACTIVE;
785 }
786 quests[Q_LTBANNER]._qlog = TRUE;
787 towner[t]._tbtcnt = 150;
788 towner[t]._tVar1 = p;
789 InitQTextMsg(TEXT_BANNER2);
790 towner[t]._tMsgSaid = TRUE;
791 }
792 if (quests[Q_LTBANNER]._qvar2 == 1 && PlrHasItem(p, IDI_BANNER, &i) != NULL && !towner[t]._tMsgSaid) {
793 quests[Q_LTBANNER]._qactive = QUEST_DONE;
794 quests[Q_LTBANNER]._qvar1 = 3;
795 RemoveInvItem(p, i);
796 SpawnUnique(UITEM_HARCREST, towner[t]._tx, towner[t]._ty + 1);
797 towner[t]._tbtcnt = 150;
798 towner[t]._tVar1 = p;
799 InitQTextMsg(TEXT_BANNER3);
800 towner[t]._tMsgSaid = TRUE;
801 }
802 }
803 }
804 if (!qtextflag) {
805 TownerTalk(TEXT_OGDEN1, t);
806 if (storeflag) {
807 StartStore(STORE_TAVERN);
808 }
809 }
810 } else if (t == GetActiveTowner(TOWN_DEADGUY)) {
811 if (quests[Q_BUTCHER]._qactive == QUEST_ACTIVE && quests[Q_BUTCHER]._qvar1 == 1) {
812 towner[t]._tbtcnt = 150;
813 towner[t]._tVar1 = p;
814 quests[Q_BUTCHER]._qvar1 = 1;
815 if (plr[p]._pClass == PC_WARRIOR && !effect_is_playing(PS_WARR8)) {
816 PlaySFX(PS_WARR8);
817 } else if (plr[p]._pClass == PC_ROGUE && !effect_is_playing(PS_ROGUE8)) {
818 PlaySFX(PS_ROGUE8);
819 } else if (plr[p]._pClass == PC_SORCERER && !effect_is_playing(PS_MAGE8)) {
820 PlaySFX(PS_MAGE8);
821 } else if (plr[p]._pClass == PC_MONK && !effect_is_playing(PS_MONK8)) {
822 PlaySFX(PS_MONK8);
823 } else if (plr[p]._pClass == PC_BARD && !effect_is_playing(PS_ROGUE8)) {
824 PlaySFX(PS_ROGUE8);
825 } else if (plr[p]._pClass == PC_BARBARIAN && !effect_is_playing(PS_WARR8)) {
826 PlaySFX(PS_WARR8);
827 }
828 towner[t]._tMsgSaid = TRUE;
829 } else if (quests[Q_BUTCHER]._qactive == QUEST_DONE && quests[Q_BUTCHER]._qvar1 == 1) {
830 quests[Q_BUTCHER]._qvar1 = 1;
831 towner[t]._tbtcnt = 150;
832 towner[t]._tVar1 = p;
833 towner[t]._tMsgSaid = TRUE;
834 } else if (quests[Q_BUTCHER]._qactive == QUEST_INIT || (quests[Q_BUTCHER]._qactive == QUEST_ACTIVE && quests[Q_BUTCHER]._qvar1 == 0)) {
835 quests[Q_BUTCHER]._qactive = QUEST_ACTIVE;
836 quests[Q_BUTCHER]._qlog = TRUE;
837 quests[Q_BUTCHER]._qmsg = TEXT_BUTCH9;
838 quests[Q_BUTCHER]._qvar1 = 1;
839 towner[t]._tbtcnt = 50;
840 towner[t]._tVar1 = p;
841 towner[t]._tVar2 = 3;
842 InitQTextMsg(TEXT_BUTCH9);
843 towner[t]._tMsgSaid = TRUE;
844 NetSendCmdQuest(TRUE, Q_BUTCHER);
845 }
846 } else if (t == GetActiveTowner(TOWN_SMITH)) {
847 if (!gbIsMultiplayer) {
848 if (plr[p]._pLvlVisited[4] && quests[Q_ROCK]._qactive != QUEST_NOTAVAIL) {
849 if (quests[Q_ROCK]._qvar2 == 0) {
850 quests[Q_ROCK]._qvar2 = 1;
851 quests[Q_ROCK]._qlog = TRUE;
852 if (quests[Q_ROCK]._qactive == QUEST_INIT) {
853 quests[Q_ROCK]._qactive = QUEST_ACTIVE;
854 quests[Q_ROCK]._qvar1 = 1;
855 }
856 towner[t]._tbtcnt = 150;
857 towner[t]._tVar1 = p;
858 InitQTextMsg(TEXT_INFRA5);
859 towner[t]._tMsgSaid = TRUE;
860 }
861 if (quests[Q_ROCK]._qvar2 == 1 && PlrHasItem(p, IDI_ROCK, &i) != NULL && !towner[t]._tMsgSaid) {
862 quests[Q_ROCK]._qactive = QUEST_DONE;
863 quests[Q_ROCK]._qvar2 = 2;
864 quests[Q_ROCK]._qvar1 = 2;
865 RemoveInvItem(p, i);
866 SpawnUnique(UITEM_INFRARING, towner[t]._tx, towner[t]._ty + 1);
867 towner[t]._tbtcnt = 150;
868 towner[t]._tVar1 = p;
869 InitQTextMsg(TEXT_INFRA7);
870 towner[t]._tMsgSaid = TRUE;
871 }
872 }
873 if (plr[p]._pLvlVisited[9] && quests[Q_ANVIL]._qactive != QUEST_NOTAVAIL) {
874 if ((quests[Q_ANVIL]._qactive == QUEST_INIT || quests[Q_ANVIL]._qactive == QUEST_ACTIVE) && quests[Q_ANVIL]._qvar2 == 0 && !towner[t]._tMsgSaid) {
875 if (quests[Q_ROCK]._qvar2 == 2 || (quests[Q_ROCK]._qactive == QUEST_ACTIVE && quests[Q_ROCK]._qvar2 == 1)) {
876 quests[Q_ANVIL]._qvar2 = 1;
877 quests[Q_ANVIL]._qlog = TRUE;
878 if (quests[Q_ANVIL]._qactive == QUEST_INIT) {
879 quests[Q_ANVIL]._qactive = QUEST_ACTIVE;
880 quests[Q_ANVIL]._qvar1 = 1;
881 }
882 towner[t]._tbtcnt = 150;
883 towner[t]._tVar1 = p;
884 InitQTextMsg(TEXT_ANVIL5);
885 towner[t]._tMsgSaid = TRUE;
886 }
887 }
888 if (quests[Q_ANVIL]._qvar2 == 1 && PlrHasItem(p, IDI_ANVIL, &i) != NULL) {
889 if (!towner[t]._tMsgSaid) {
890 quests[Q_ANVIL]._qactive = QUEST_DONE;
891 quests[Q_ANVIL]._qvar2 = 2;
892 quests[Q_ANVIL]._qvar1 = 2;
893 RemoveInvItem(p, i);
894 SpawnUnique(UITEM_GRISWOLD, towner[t]._tx, towner[t]._ty + 1);
895 towner[t]._tbtcnt = 150;
896 towner[t]._tVar1 = p;
897 InitQTextMsg(TEXT_ANVIL7);
898 towner[t]._tMsgSaid = TRUE;
899 }
900 }
901 }
902 }
903 if (!qtextflag) {
904 TownerTalk(TEXT_GRISWOLD1, t);
905 if (storeflag) {
906 StartStore(STORE_SMITH);
907 }
908 }
909 } else if (t == GetActiveTowner(TOWN_WITCH)) {
910 if (quests[Q_MUSHROOM]._qactive == QUEST_INIT && PlrHasItem(p, IDI_FUNGALTM, &i) != NULL) {
911 RemoveInvItem(p, i);
912 quests[Q_MUSHROOM]._qactive = QUEST_ACTIVE;
913 quests[Q_MUSHROOM]._qlog = TRUE;
914 quests[Q_MUSHROOM]._qvar1 = QS_TOMEGIVEN;
915 towner[t]._tbtcnt = 150;
916 towner[t]._tVar1 = p;
917 InitQTextMsg(TEXT_MUSH8);
918 towner[t]._tMsgSaid = TRUE;
919 } else if (quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE) {
920 if (quests[Q_MUSHROOM]._qvar1 >= QS_TOMEGIVEN && quests[Q_MUSHROOM]._qvar1 <= QS_MUSHPICKED) {
921 if (PlrHasItem(p, IDI_MUSHROOM, &i) != NULL) {
922 RemoveInvItem(p, i);
923 quests[Q_MUSHROOM]._qvar1 = 5;
924 Qtalklist[TOWN_HEALER][Q_MUSHROOM] = TEXT_MUSH3;
925 Qtalklist[TOWN_WITCH][Q_MUSHROOM] = TEXT_NONE;
926 towner[t]._tbtcnt = 150;
927 towner[t]._tVar1 = p;
928 quests[Q_MUSHROOM]._qmsg = TEXT_MUSH10;
929 InitQTextMsg(TEXT_MUSH10);
930 towner[t]._tMsgSaid = TRUE;
931 } else if (quests[Q_MUSHROOM]._qmsg != TEXT_MUSH9) {
932 towner[t]._tbtcnt = 150;
933 towner[t]._tVar1 = p;
934 quests[Q_MUSHROOM]._qmsg = TEXT_MUSH9;
935 InitQTextMsg(TEXT_MUSH9);
936 towner[t]._tMsgSaid = TRUE;
937 }
938 } else {
939 Item = PlrHasItem(p, IDI_SPECELIX, &i);
940 if (Item != NULL) {
941 towner[t]._tbtcnt = 150;
942 towner[t]._tVar1 = p;
943 InitQTextMsg(TEXT_MUSH12);
944 quests[Q_MUSHROOM]._qactive = QUEST_DONE;
945 towner[t]._tMsgSaid = TRUE;
946 AllItemsList[Item->IDidx].iUsable = TRUE;
947 } else if (PlrHasItem(p, IDI_BRAIN, &i) != NULL && quests[Q_MUSHROOM]._qvar2 != TEXT_MUSH11) {
948 towner[t]._tbtcnt = 150;
949 towner[t]._tVar1 = p;
950 quests[Q_MUSHROOM]._qvar2 = TEXT_MUSH11;
951 InitQTextMsg(TEXT_MUSH11);
952 towner[t]._tMsgSaid = TRUE;
953 }
954 }
955 }
956 if (!qtextflag) {
957 TownerTalk(TEXT_ADRIA1, t);
958 if (storeflag) {
959 StartStore(STORE_WITCH);
960 }
961 }
962 } else if (t == GetActiveTowner(TOWN_BMAID)) {
963 if (plr[p]._pLvlVisited[21] == false && PlrHasItem(p, IDI_MAPOFDOOM, &i)) {
964 quests[Q_GRAVE]._qactive = 2;
965 quests[Q_GRAVE]._qlog = 1;
966 quests[Q_GRAVE]._qmsg = TEXT_GRAVE8;
967 InitQTextMsg(TEXT_GRAVE8);
968 towner[t]._tMsgSaid = TRUE;
969 }
970 if (!qtextflag) {
971 TownerTalk(TEXT_GILLIAN1, t);
972 if (storeflag) {
973 StartStore(STORE_BARMAID);
974 }
975 }
976 } else if (t == GetActiveTowner(TOWN_DRUNK)) {
977 if (!qtextflag) {
978 TownerTalk(TEXT_FARNHAM1, t);
979 if (storeflag) {
980 StartStore(STORE_DRUNK);
981 }
982 }
983 } else if (t == GetActiveTowner(TOWN_HEALER)) {
984 if (!gbIsMultiplayer) {
985 if (plr[p]._pLvlVisited[1] || (gbIsHellfire && plr[p]._pLvlVisited[5])) {
986 if (!towner[t]._tMsgSaid) {
987 if (quests[Q_PWATER]._qactive == QUEST_INIT) {
988 quests[Q_PWATER]._qactive = QUEST_ACTIVE;
989 quests[Q_PWATER]._qlog = TRUE;
990 quests[Q_PWATER]._qmsg = TEXT_POISON3;
991 quests[Q_PWATER]._qvar1 = 1;
992 towner[t]._tbtcnt = 150;
993 towner[t]._tVar1 = p;
994 InitQTextMsg(TEXT_POISON3);
995 towner[t]._tMsgSaid = TRUE;
996 } else if (quests[Q_PWATER]._qactive == QUEST_DONE && quests[Q_PWATER]._qvar1 != 2) {
997 quests[Q_PWATER]._qvar1 = 2;
998 towner[t]._tbtcnt = 150;
999 towner[t]._tVar1 = p;
1000 InitQTextMsg(TEXT_POISON5);
1001 SpawnUnique(UITEM_TRING, towner[t]._tx, towner[t]._ty + 1);
1002 towner[t]._tMsgSaid = TRUE;
1003 }
1004 }
1005 }
1006 if (quests[Q_MUSHROOM]._qactive == QUEST_ACTIVE && quests[Q_MUSHROOM]._qmsg == TEXT_MUSH10 && PlrHasItem(p, IDI_BRAIN, &i) != NULL) {
1007 RemoveInvItem(p, i);
1008 SpawnQuestItem(IDI_SPECELIX, towner[t]._tx, towner[t]._ty + 1, 0, 0);
1009 InitQTextMsg(TEXT_MUSH4);
1010 quests[Q_MUSHROOM]._qvar1 = QS_BRAINGIVEN;
1011 Qtalklist[TOWN_HEALER][Q_MUSHROOM] = TEXT_NONE;
1012 }
1013 }
1014 if (!qtextflag) {
1015 TownerTalk(TEXT_PEPIN1, t);
1016 if (storeflag) {
1017 StartStore(STORE_HEALER);
1018 }
1019 }
1020 } else if (t == GetActiveTowner(TOWN_PEGBOY)) {
1021 if (!qtextflag) {
1022 TownerTalk(TEXT_WIRT1, t);
1023 if (storeflag) {
1024 StartStore(STORE_BOY);
1025 }
1026 }
1027 } else if (t == GetActiveTowner(TOWN_STORY)) {
1028 if (!gbIsMultiplayer) {
1029 if (quests[Q_BETRAYER]._qactive == QUEST_INIT && PlrHasItem(p, IDI_LAZSTAFF, &i) != NULL) {
1030 RemoveInvItem(p, i);
1031 quests[Q_BETRAYER]._qvar1 = 2;
1032 towner[t]._tbtcnt = 150;
1033 towner[t]._tVar1 = p;
1034 InitQTextMsg(TEXT_VILE1);
1035 towner[t]._tMsgSaid = TRUE;
1036 quests[Q_BETRAYER]._qactive = QUEST_ACTIVE;
1037 quests[Q_BETRAYER]._qlog = TRUE;
1038 } else if (quests[Q_BETRAYER]._qactive == QUEST_DONE && quests[Q_BETRAYER]._qvar1 == 7) {
1039 quests[Q_BETRAYER]._qvar1 = 8;
1040 towner[t]._tbtcnt = 150;
1041 towner[t]._tVar1 = p;
1042 InitQTextMsg(TEXT_VILE3);
1043 towner[t]._tMsgSaid = TRUE;
1044 quests[Q_DIABLO]._qlog = TRUE;
1045 }
1046 }
1047 if (gbIsMultiplayer) {
1048 if (quests[Q_BETRAYER]._qactive == QUEST_ACTIVE && !quests[Q_BETRAYER]._qlog) {
1049 towner[t]._tbtcnt = 150;
1050 towner[t]._tVar1 = p;
1051 InitQTextMsg(TEXT_VILE1);
1052 towner[t]._tMsgSaid = TRUE;
1053 quests[Q_BETRAYER]._qlog = TRUE;
1054 NetSendCmdQuest(TRUE, Q_BETRAYER);
1055 } else if (quests[Q_BETRAYER]._qactive == QUEST_DONE && quests[Q_BETRAYER]._qvar1 == 7) {
1056 quests[Q_BETRAYER]._qvar1 = 8;
1057 towner[t]._tbtcnt = 150;
1058 towner[t]._tVar1 = p;
1059 InitQTextMsg(TEXT_VILE3);
1060 towner[t]._tMsgSaid = TRUE;
1061 NetSendCmdQuest(TRUE, Q_BETRAYER);
1062 quests[Q_DIABLO]._qlog = TRUE;
1063 NetSendCmdQuest(TRUE, Q_DIABLO);
1064 }
1065 }
1066 if (!qtextflag) {
1067 TownerTalk(TEXT_STORY1, t);
1068 if (storeflag) {
1069 StartStore(STORE_STORY);
1070 }
1071 }
1072 } else if (towner[t]._ttype == TOWN_COW) {
1073 if (!qtextflag)
1074 CowSFX(p);
1075 } else if (towner[t]._ttype == TOWN_FARMER) {
1076 if (!qtextflag) {
1077 qt = TEXT_FARMER1;
1078 t2 = 1;
1079 switch (quests[Q_FARMER]._qactive) {
1080 case 0:
1081 if (PlrHasItem(p, IDI_RUNEBOMB, &i)) {
1082 qt = TEXT_FARMER2;
1083 quests[Q_FARMER]._qactive = 2;
1084 quests[Q_FARMER]._qvar1 = 1;
1085 quests[Q_FARMER]._qlog = 1;
1086 quests[Q_FARMER]._qmsg = TEXT_FARMER1;
1087 break;
1088 } else if (!plr[p]._pLvlVisited[9] && plr[p]._pLevel < 15) {
1089 qt = TEXT_FARMER8;
1090 if (plr[p]._pLvlVisited[2])
1091 qt = TEXT_FARMER5;
1092 if (plr[p]._pLvlVisited[5])
1093 qt = TEXT_FARMER7;
1094 if (plr[p]._pLvlVisited[7])
1095 qt = TEXT_FARMER9;
1096 } else {
1097 qt = TEXT_FARMER1;
1098 quests[Q_FARMER]._qactive = 2;
1099 quests[Q_FARMER]._qvar1 = 1;
1100 quests[Q_FARMER]._qlog = 1;
1101 quests[Q_FARMER]._qmsg = TEXT_FARMER1;
1102 SpawnRuneBomb(towner[t]._tx + 1, towner[t]._ty);
1103 t2 = 1;
1104 break;
1105 }
1106 case 2:
1107 if (PlrHasItem(p, IDI_RUNEBOMB, &i))
1108 qt = TEXT_FARMER2;
1109 else
1110 qt = TEXT_FARMER3;
1111 break;
1112 case 1:
1113 if (PlrHasItem(p, IDI_RUNEBOMB, &i)) {
1114 qt = TEXT_FARMER2;
1115 quests[Q_FARMER]._qactive = 2;
1116 quests[Q_FARMER]._qvar1 = 1;
1117 quests[Q_FARMER]._qmsg = TEXT_FARMER1;
1118 quests[Q_FARMER]._qlog = 1;
1119 } else if (!plr[p]._pLvlVisited[9] && plr[p]._pLevel < 15) {
1120 qt = TEXT_FARMER8;
1121 if (plr[p]._pLvlVisited[2]) {
1122 qt = TEXT_FARMER5;
1123 }
1124 if (plr[p]._pLvlVisited[5]) {
1125 qt = TEXT_FARMER7;
1126 }
1127 if (plr[p]._pLvlVisited[7]) {
1128 qt = TEXT_FARMER9;
1129 }
1130 } else {
1131 qt = TEXT_FARMER1;
1132 quests[Q_FARMER]._qactive = 2;
1133 quests[Q_FARMER]._qvar1 = 1;
1134 quests[Q_FARMER]._qlog = 1;
1135 quests[Q_FARMER]._qmsg = TEXT_FARMER1;
1136 SpawnRuneBomb(towner[t]._tx + 1, towner[t]._ty);
1137 t2 = 1;
1138 }
1139 break;
1140 case 3:
1141 qt = TEXT_FARMER4;
1142 SpawnRewardItem(IDI_AURIC, towner[t]._tx + 1, towner[t]._ty);
1143 quests[Q_FARMER]._qactive = 10;
1144 quests[Q_FARMER]._qlog = 0;
1145 t2 = 1;
1146 break;
1147 case 10:
1148 qt = TEXT_NONE;
1149 break;
1150 default:
1151 quests[Q_FARMER]._qactive = 0;
1152 qt = TEXT_FARMER4;
1153 break;
1154 }
1155 if (qt != TEXT_NONE) {
1156 if (t2)
1157 InitQTextMsg(qt);
1158 else
1159 PlaySFX(alltext[qt].sfxnr);
1160 }
1161 if (gbIsMultiplayer) {
1162 NetSendCmdQuest(TRUE, Q_FARMER);
1163 }
1164 }
1165 } else if (towner[t]._ttype == TOWN_COWFARM) {
1166 if (!qtextflag) {
1167 qt = TEXT_JERSEY1;
1168 t2 = 1;
1169 if (PlrHasItem(p, IDI_GREYSUIT, &i)) {
1170 qt = TEXT_JERSEY7;
1171 RemoveInvItem(p, i);
1172 } else if (PlrHasItem(p, IDI_BROWNSUIT, &i)) {
1173 SpawnUnique(UITEM_BOVINE, towner[t]._tx + 1, towner[t]._ty);
1174 RemoveInvItem(p, i);
1175 qt = TEXT_JERSEY8;
1176 quests[Q_JERSEY]._qactive = 3;
1177 } else if (PlrHasItem(p, IDI_RUNEBOMB, &i)) {
1178 qt = TEXT_JERSEY5;
1179 quests[Q_JERSEY]._qactive = 2;
1180 quests[Q_JERSEY]._qvar1 = 1;
1181 quests[Q_JERSEY]._qmsg = TEXT_JERSEY4;
1182 quests[Q_JERSEY]._qlog = 1;
1183 } else {
1184 switch (quests[Q_JERSEY]._qactive) {
1185 case 0:
1186 qt = TEXT_JERSEY1;
1187 quests[Q_JERSEY]._qactive = 7;
1188 break;
1189 case 1:
1190 qt = TEXT_JERSEY1;
1191 quests[23]._qactive = 7;
1192 break;
1193 case 2:
1194 qt = TEXT_JERSEY5;
1195 break;
1196 case 3:
1197 qt = TEXT_JERSEY1;
1198 break;
1199 case 7:
1200 qt = TEXT_JERSEY2;
1201 quests[Q_JERSEY]._qactive = 8;
1202 break;
1203 case 8:
1204 qt = TEXT_JERSEY3;
1205 quests[Q_JERSEY]._qactive = 9;
1206 break;
1207 case 9:
1208 if (!plr[p]._pLvlVisited[9] && plr[p]._pLevel < 15) {
1209 switch (random_(0, 4) + 9) {
1210 case 9:
1211 qt = TEXT_JERSEY9;
1212 break;
1213 case 10:
1214 qt = TEXT_JERSEY10;
1215 break;
1216 case 11:
1217 qt = TEXT_JERSEY11;
1218 break;
1219 default:
1220 qt = TEXT_JERSEY12;
1221 }
1222 break;
1223 } else {
1224 qt = TEXT_JERSEY4;
1225 quests[Q_JERSEY]._qactive = 2;
1226 quests[Q_JERSEY]._qvar1 = 1;
1227 quests[Q_JERSEY]._qmsg = TEXT_JERSEY4;
1228 quests[Q_JERSEY]._qlog = 1;
1229 SpawnRuneBomb(towner[t]._tx + 1, towner[t]._ty);
1230 t2 = 1;
1231 }
1232 break;
1233 default:
1234 qt = TEXT_JERSEY5;
1235 quests[Q_JERSEY]._qactive = 0;
1236 break;
1237 }
1238 }
1239 if (qt != -1) {
1240 if (t2)
1241 InitQTextMsg(qt);
1242 else
1243 PlaySFX(alltext[qt].sfxnr);
1244 }
1245 if (gbIsMultiplayer) {
1246 NetSendCmdQuest(TRUE, Q_JERSEY);
1247 }
1248 }
1249 } else if (towner[t]._ttype == TOWN_GIRL) {
1250 if (!qtextflag) {
1251 qt = TEXT_GIRL1;
1252 t2 = 0;
1253 if (!PlrHasItem(p, IDI_THEODORE, &i) || quests[Q_GIRL]._qactive == 3) {
1254 switch (quests[Q_GIRL]._qactive) {
1255 case 0:
1256 qt = TEXT_GIRL2;
1257 quests[Q_GIRL]._qactive = 2;
1258 quests[Q_GIRL]._qvar1 = 1;
1259 quests[Q_GIRL]._qlog = 1;
1260 quests[Q_GIRL]._qmsg = TEXT_GIRL2;
1261 t2 = 1;
1262 break;
1263 case 1:
1264 qt = TEXT_GIRL2;
1265 quests[Q_GIRL]._qvar1 = 1;
1266 quests[Q_GIRL]._qlog = 1;
1267 quests[Q_GIRL]._qmsg = TEXT_GIRL2;
1268 quests[Q_GIRL]._qactive = 2;
1269 t2 = 1;
1270 break;
1271 case 2:
1272 qt = TEXT_GIRL3;
1273 t2 = 1;
1274 break;
1275 case 3:
1276 qt = TEXT_NONE;
1277 break;
1278 default:
1279 quests[Q_GIRL]._qactive = 0;
1280 qt = TEXT_GIRL1;
1281 break;
1282 }
1283 } else {
1284 qt = TEXT_GIRL4;
1285 RemoveInvItem(p, i);
1286 CreateAmulet(towner[t]._tx, towner[t]._ty, 13, 0, 1);
1287 quests[Q_GIRL]._qlog = 0;
1288 quests[Q_GIRL]._qactive = 3;
1289 t2 = 1;
1290 }
1291 if (qt != -1) {
1292 if (t2 != 0) {
1293 InitQTextMsg(qt);
1294 } else {
1295 PlaySFX(alltext[qt].sfxnr);
1296 }
1297 }
1298 if (gbIsMultiplayer) {
1299 NetSendCmdQuest(TRUE, Q_GIRL);
1300 }
1301 }
1302 }
1303 }
1304
1305 DEVILUTION_END_NAMESPACE
1306