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