251
|
1 #include <string.h>
|
|
2 #include <stdlib.h>
|
|
3
|
|
4 #include "Allocator.h"
|
|
5 #include "texts.h"
|
|
6 #include "Party.h"
|
|
7 #include "LOD.h"
|
|
8 #include "Autonotes.h"
|
|
9 #include "Awards.h"
|
|
10 #include "mm7_data.h"
|
|
11 #include "MM7.h"
|
|
12 #include "NPC.h"
|
|
13
|
|
14
|
629
|
15 int pDialogueNPCCount;
|
|
16 struct Texture *pDialogueNPCPortraits[6];
|
|
17 int uNumDialogueNPCPortraits; // weak
|
|
18 struct NPCStats *pNPCStats = nullptr;
|
|
19
|
251
|
20 void InitializeAwards();
|
|
21 void InitializeScrolls();
|
|
22 void InitializeMerchants();
|
|
23 void InitializeTransitions();
|
|
24 void InitializeAutonotes();
|
|
25 void InitializeQuests();
|
307
|
26 bool CheckPortretAgainstSex(int portret_num, int sex);
|
251
|
27
|
|
28 //----- (00476977) --------------------------------------------------------
|
291
|
29 void NPCStats::InitializeNPCText()
|
251
|
30 {
|
|
31 int i;
|
|
32 char* test_string;
|
|
33 unsigned char c;
|
|
34 bool break_loop;
|
|
35 unsigned int temp_str_len;
|
|
36 char* tmp_pos;
|
|
37 int decode_step;
|
|
38
|
|
39 if (pNPCTextTXT_Raw)
|
|
40 pAllocator->FreeChunk(pNPCTextTXT_Raw);
|
|
41 pNPCTextTXT_Raw =NULL;
|
|
42 pNPCTextTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctext.txt", 0);
|
|
43 strtok(pNPCTextTXT_Raw, "\r");
|
|
44
|
|
45 for (i=0; i<789; ++i)
|
|
46 {
|
|
47 test_string = strtok(NULL, "\r") + 1;
|
|
48 break_loop = false;
|
|
49 decode_step=0;
|
|
50 do
|
|
51 {
|
|
52 c = *(unsigned char*)test_string;
|
|
53 temp_str_len = 0;
|
|
54 while((c!='\t')&&(c>0))
|
|
55 {
|
|
56 ++temp_str_len;
|
|
57 c=test_string[temp_str_len];
|
|
58 }
|
|
59 tmp_pos=test_string+temp_str_len;
|
|
60 if (*tmp_pos == 0)
|
|
61 break_loop = true;
|
|
62 *tmp_pos = 0;
|
|
63 if (temp_str_len)
|
|
64 {
|
|
65 if ( decode_step == 1)
|
|
66 pNPCTopics[i].pText =RemoveQuotes(test_string);
|
|
67 }
|
|
68 else
|
|
69 {
|
|
70 break_loop = true;
|
|
71 }
|
|
72 ++decode_step;
|
|
73 test_string=tmp_pos+1;
|
|
74 } while ((decode_step<2)&&!break_loop);
|
|
75 }
|
|
76
|
|
77 if (pNPCTopicTXT_Raw)
|
|
78 pAllocator->FreeChunk(pNPCTopicTXT_Raw);
|
|
79 pNPCTopicTXT_Raw =NULL;
|
|
80 pNPCTopicTXT_Raw = (char *)pEvents_LOD->LoadRaw("npctopic.txt", 0);
|
|
81 strtok(pNPCTopicTXT_Raw, "\r");
|
|
82
|
|
83 for (i=0; i<579; ++i)
|
|
84 {
|
|
85 test_string = strtok(NULL, "\r") + 1;
|
|
86 break_loop = false;
|
|
87 decode_step=0;
|
|
88 do
|
|
89 {
|
|
90 c = *(unsigned char*)test_string;
|
|
91 temp_str_len = 0;
|
|
92 while((c!='\t')&&(c>0))
|
|
93 {
|
|
94 ++temp_str_len;
|
|
95 c=test_string[temp_str_len];
|
|
96 }
|
|
97 tmp_pos=test_string+temp_str_len;
|
|
98 if (*tmp_pos == 0)
|
|
99 break_loop = true;
|
|
100 *tmp_pos = 0;
|
|
101 if (temp_str_len)
|
|
102 {
|
|
103 if ( decode_step == 1)
|
|
104 pNPCTopics[i].pTopic = RemoveQuotes(test_string);
|
|
105 }
|
|
106 else
|
|
107 {
|
|
108 break_loop = true;
|
|
109 }
|
|
110 ++decode_step;
|
|
111 test_string=tmp_pos+1;
|
|
112 } while ((decode_step<2)&&!break_loop);
|
|
113 }
|
|
114
|
|
115 if (pNPCDistTXT_Raw)
|
|
116 pAllocator->FreeChunk(pNPCDistTXT_Raw);
|
|
117 pNPCDistTXT_Raw = NULL;
|
|
118 pNPCDistTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcdist.txt", 0);
|
|
119 strtok(pNPCDistTXT_Raw, "\r");
|
|
120 strtok(NULL, "\r");
|
|
121
|
|
122 for (i=1; i<59; ++i)
|
|
123 {
|
|
124 test_string = strtok(NULL, "\r") + 1;
|
|
125 break_loop = false;
|
|
126 decode_step=0;
|
|
127 do
|
|
128 {
|
|
129 c = *(unsigned char*)test_string;
|
|
130 temp_str_len = 0;
|
|
131 while((c!='\t')&&(c>0))
|
|
132 {
|
|
133 ++temp_str_len;
|
|
134 c=test_string[temp_str_len];
|
|
135 }
|
|
136 tmp_pos=test_string+temp_str_len;
|
|
137 if (*tmp_pos == 0)
|
|
138 break_loop = true;
|
|
139 *tmp_pos = 0;
|
|
140 if (temp_str_len)
|
|
141 {
|
|
142 if ((decode_step>0)&&(decode_step<77))
|
|
143 {
|
291
|
144 pProfessionChance[decode_step].professionChancePerArea[i]=atoi(test_string);
|
251
|
145 }
|
|
146 else if (decode_step==0)
|
|
147 {
|
291
|
148 pProfessionChance[0].professionChancePerArea[i]=10;
|
251
|
149 }
|
|
150 }
|
|
151 else
|
|
152 {
|
|
153 break_loop = true;
|
|
154 }
|
|
155 ++decode_step;
|
|
156 test_string=tmp_pos+1;
|
|
157 } while ((decode_step<78)&&!break_loop);
|
|
158 }
|
|
159
|
|
160 for (i=0; i<78; ++i)
|
|
161 {
|
291
|
162 pProfessionChance[i].uTotalprofChance=0;
|
251
|
163 for (int ii=1; ii<59; ++ii)
|
|
164 {
|
291
|
165 pProfessionChance[i].uTotalprofChance+=pProfessionChance[i].professionChancePerArea[ii];
|
251
|
166 }
|
293
|
167 pProfessionChance[i].professionChancePerArea[0]=0;
|
|
168 pProfessionChance[i].professionChancePerArea[59]=0;
|
251
|
169 }
|
|
170
|
|
171 if (pNPCDistTXT_Raw)
|
|
172 {
|
|
173 pAllocator->FreeChunk(pNPCDistTXT_Raw);
|
|
174 pNPCDistTXT_Raw = NULL;
|
|
175 }
|
|
176 }
|
|
177
|
|
178 //----- (00476C60) --------------------------------------------------------
|
|
179 void NPCStats::_476C60()
|
|
180 {
|
|
181 for (unsigned int i = 1; i < uNumNewNPCs; ++i)
|
291
|
182 pNewNPCData[i].pName = pNPCUnicNames[i - 1];
|
251
|
183
|
|
184 if (pParty->pHirelings[0].pName)
|
|
185 pParty->pHirelings[0].pName = pParty->pHireling1Name;
|
|
186 if (pParty->pHirelings[1].pName)
|
|
187 pParty->pHirelings[1].pName = pParty->pHireling2Name;
|
|
188 }
|
|
189
|
|
190 //----- (00476CB5) --------------------------------------------------------
|
291
|
191 void NPCStats::InitializeNPCData()
|
251
|
192 {
|
291
|
193 int i;
|
|
194 char* test_string;
|
|
195 unsigned char c;
|
|
196 bool break_loop;
|
|
197 unsigned int temp_str_len;
|
|
198 char* tmp_pos;
|
|
199 int decode_step;
|
|
200
|
|
201 pNPCDataTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcdata.txt", 0);
|
|
202 strtok(pNPCDataTXT_Raw, "\r");
|
|
203 strtok(NULL, "\r");
|
251
|
204
|
291
|
205 for (i=0; i<500; ++i)
|
251
|
206 {
|
291
|
207 test_string = strtok(NULL, "\r") + 1;
|
|
208 break_loop = false;
|
|
209 decode_step=0;
|
|
210 do
|
251
|
211 {
|
291
|
212 c = *(unsigned char*)test_string;
|
|
213 temp_str_len = 0;
|
|
214 while((c!='\t')&&(c>0))
|
251
|
215 {
|
291
|
216 ++temp_str_len;
|
|
217 c=test_string[temp_str_len];
|
|
218 }
|
|
219 tmp_pos=test_string+temp_str_len;
|
|
220 if (*tmp_pos == 0)
|
|
221 break_loop = true;
|
|
222 *tmp_pos = 0;
|
|
223 if (temp_str_len)
|
|
224 { //i+1
|
|
225 switch (decode_step)
|
251
|
226 {
|
291
|
227 case 1:
|
|
228 pNPCUnicNames[i] = RemoveQuotes(test_string);
|
|
229 pNPCData[i+1].pName=pNPCUnicNames[i];
|
251
|
230 break;
|
291
|
231 case 2:
|
|
232 pNPCData[i+1].uPortraitID = atoi(test_string);
|
251
|
233 break;
|
|
234 case 6:
|
291
|
235 pNPCData[i+1].Location2D = atoi(test_string);
|
251
|
236 break;
|
|
237 case 7:
|
291
|
238 pNPCData[i+1].uProfession = atoi(test_string);
|
251
|
239 break;
|
|
240 case 8:
|
291
|
241 pNPCData[i+1].greet = atoi(test_string);
|
251
|
242 break;
|
|
243 case 9:
|
291
|
244 pNPCData[i+1].joins = (*test_string == 'y')?1:0;
|
251
|
245 break;
|
|
246 case 10:
|
291
|
247 pNPCData[i+1].evt_A = atoi(test_string);
|
251
|
248 break;
|
|
249 case 11:
|
291
|
250 pNPCData[i+1].evt_B = atoi(test_string);
|
251
|
251 break;
|
|
252 case 12:
|
291
|
253 pNPCData[i+1].evt_C = atoi(test_string);
|
251
|
254 break;
|
|
255 case 13:
|
291
|
256 pNPCData[i+1].evt_D = atoi(test_string);
|
251
|
257 break;
|
|
258 case 14:
|
291
|
259 pNPCData[i+1].evt_E = atoi(test_string);
|
251
|
260 break;
|
291
|
261 case 15:
|
|
262 pNPCData[i+1].evt_F = atoi(test_string);
|
251
|
263 break;
|
|
264 }
|
|
265 }
|
291
|
266 ++decode_step;
|
|
267 test_string=tmp_pos+1;
|
|
268 } while ((decode_step<16)&&!break_loop);
|
251
|
269 }
|
291
|
270 uNumNewNPCs = 501;
|
|
271 pNPCGreetTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcgreet.txt", 0);
|
|
272 strtok(pNPCGreetTXT_Raw, "\r");
|
|
273 for (i=0; i<205; ++i)
|
|
274 {
|
|
275 test_string = strtok(NULL, "\r") + 1;
|
|
276 break_loop = false;
|
|
277 decode_step=0;
|
|
278 do
|
251
|
279 {
|
291
|
280 c = *(unsigned char*)test_string;
|
|
281 temp_str_len = 0;
|
|
282 while((c!='\t')&&(c>0))
|
251
|
283 {
|
291
|
284 ++temp_str_len;
|
|
285 c=test_string[temp_str_len];
|
|
286 }
|
|
287 tmp_pos=test_string+temp_str_len;
|
|
288 if (*tmp_pos == 0)
|
|
289 break_loop = true;
|
|
290 *tmp_pos = 0;
|
|
291 if (temp_str_len)
|
|
292 { //i+1
|
|
293 switch (decode_step)
|
251
|
294 {
|
291
|
295 case 1:
|
|
296 pNPCGreetings[i].pGreeting1 = RemoveQuotes(test_string);
|
|
297 break;
|
|
298 case 2:
|
|
299 pNPCGreetings[i].pGreeting2 = RemoveQuotes(test_string);
|
|
300 break;
|
251
|
301 }
|
|
302 }
|
291
|
303 ++decode_step;
|
|
304 test_string=tmp_pos+1;
|
|
305 } while ((decode_step<3)&&!break_loop);
|
|
306 }
|
|
307
|
|
308 pNCPGroupTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcgroup.txt", 0);
|
|
309 strtok(pNCPGroupTXT_Raw, "\r");
|
|
310
|
|
311 for (i=0; i<51; ++i)
|
|
312 {
|
|
313 test_string = strtok(NULL, "\r") + 1;
|
|
314 break_loop = false;
|
|
315 decode_step=0;
|
|
316 do
|
|
317 {
|
|
318 c = *(unsigned char*)test_string;
|
|
319 temp_str_len = 0;
|
|
320 while((c!='\t')&&(c>0))
|
|
321 {
|
|
322 ++temp_str_len;
|
|
323 c=test_string[temp_str_len];
|
|
324 }
|
|
325 tmp_pos=test_string+temp_str_len;
|
|
326 if (*tmp_pos == 0)
|
|
327 break_loop = true;
|
|
328 *tmp_pos = 0;
|
|
329 if (temp_str_len)
|
|
330 { //i+1
|
|
331 if (decode_step==1)
|
251
|
332 {
|
291
|
333 pGroups[i] = atoi(test_string);
|
251
|
334 }
|
291
|
335 }
|
|
336 ++decode_step;
|
|
337 test_string=tmp_pos+1;
|
|
338 } while ((decode_step<2)&&!break_loop);
|
|
339 }
|
|
340
|
|
341 pNPCNewsTXT_Raw = (char*)pEvents_LOD->LoadRaw("npcnews.txt", 0);
|
|
342 strtok(pNPCNewsTXT_Raw, "\r");
|
|
343
|
|
344
|
|
345 for (i=0; i<51; ++i)
|
|
346 {
|
|
347 test_string = strtok(NULL, "\r") + 1;
|
|
348 break_loop = false;
|
|
349 decode_step=0;
|
|
350 do
|
|
351 {
|
|
352 c = *(unsigned char*)test_string;
|
|
353 temp_str_len = 0;
|
|
354 while((c!='\t')&&(c>0))
|
|
355 {
|
|
356 ++temp_str_len;
|
|
357 c=test_string[temp_str_len];
|
|
358 }
|
|
359 tmp_pos=test_string+temp_str_len;
|
|
360 if (*tmp_pos == 0)
|
|
361 break_loop = true;
|
|
362 *tmp_pos = 0;
|
|
363 if (temp_str_len)
|
|
364 { //i+1
|
|
365 if (decode_step==1)
|
|
366 pCatchPhrases[i] = RemoveQuotes(test_string);
|
|
367 }
|
|
368 ++decode_step;
|
|
369 test_string=tmp_pos+1;
|
|
370 } while ((decode_step<2)&&!break_loop);
|
|
371 }
|
251
|
372 }
|
|
373
|
|
374 //----- (0047702F) --------------------------------------------------------
|
|
375 void NPCStats::Initialize()
|
291
|
376 {
|
|
377 int i;
|
|
378 char* test_string;
|
|
379 unsigned char c;
|
|
380 bool break_loop;
|
|
381 unsigned int temp_str_len;
|
|
382 char* tmp_pos;
|
|
383 int decode_step;
|
251
|
384
|
291
|
385 InitializeNPCData();
|
|
386 InitializeNPCText();
|
|
387 InitializeQuests();
|
|
388 InitializeAutonotes();
|
|
389 InitializeAwards();
|
|
390 InitializeTransitions();
|
|
391 InitializeMerchants();
|
|
392 InitializeScrolls();
|
251
|
393
|
291
|
394 pNPCNamesTXT_Raw = NULL;
|
|
395 pNPCNamesTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcnames.txt", 0);
|
|
396 strtok(pNPCNamesTXT_Raw, "\r");
|
|
397
|
|
398 uNewlNPCBufPos = 0;
|
|
399
|
|
400 for (i=0; i<540; ++i)
|
251
|
401 {
|
291
|
402 test_string = strtok(NULL, "\r") + 1;
|
|
403 break_loop = false;
|
|
404 decode_step=0;
|
|
405 do
|
251
|
406 {
|
291
|
407 c = *(unsigned char*)test_string;
|
|
408 temp_str_len = 0;
|
|
409 if (c=='\t')
|
251
|
410 {
|
291
|
411 if ( (decode_step == 1)&&(!uNumNPCNames[1]))
|
|
412 uNumNPCNames[1]=i;
|
251
|
413 }
|
|
414 else
|
|
415 {
|
291
|
416 while((c!='\n')&&(c!='\t')&&(c>0))
|
|
417 {
|
|
418 ++temp_str_len;
|
|
419 c=test_string[temp_str_len];
|
|
420 }
|
|
421 tmp_pos=test_string+temp_str_len;
|
|
422 if (*tmp_pos == 0)
|
|
423 break_loop = true;
|
|
424
|
|
425 if (temp_str_len)
|
|
426 {
|
|
427 *tmp_pos = 0;
|
|
428 if ( decode_step == 0)
|
|
429 pNPCNames[i][0] =RemoveQuotes(test_string);
|
|
430 else if ( decode_step == 1)
|
|
431 pNPCNames[i][1] =RemoveQuotes(test_string);
|
|
432 }
|
|
433 else
|
|
434 {
|
|
435 if ( (decode_step == 1)&&(!uNumNPCNames[1]))
|
|
436 uNumNPCNames[1]=i;
|
|
437 }
|
251
|
438 }
|
291
|
439 ++decode_step;
|
|
440 test_string=tmp_pos+1;
|
|
441 } while ((decode_step<2)&&!break_loop);
|
|
442 }
|
|
443 uNumNPCNames[0] = i;
|
|
444
|
|
445 pNPCProfTXT_Raw = NULL;
|
|
446 pNPCProfTXT_Raw = (char *)pEvents_LOD->LoadRaw("npcprof.txt", 0);
|
|
447 strtok(pNPCProfTXT_Raw, "\r");
|
|
448 strtok(NULL, "\r");
|
|
449 strtok(NULL, "\r");
|
|
450 strtok(NULL, "\r");
|
|
451
|
|
452 for (i=1; i<59; ++i)
|
|
453 {
|
|
454 test_string = strtok(NULL, "\r") + 1;
|
|
455 break_loop = false;
|
|
456 decode_step=0;
|
|
457 do
|
251
|
458 {
|
652
|
459 while (*test_string == '\t') // some steps are separated by multiple \t's
|
|
460 ++test_string;
|
|
461
|
291
|
462 c = *(unsigned char*)test_string;
|
|
463 temp_str_len = 0;
|
|
464 while((c!='\t')&&(c>0))
|
251
|
465 {
|
291
|
466 ++temp_str_len;
|
|
467 c=test_string[temp_str_len];
|
|
468 }
|
|
469 tmp_pos=test_string+temp_str_len;
|
|
470 if (*tmp_pos == 0)
|
|
471 break_loop = true;
|
|
472 *tmp_pos = 0;
|
|
473 if (temp_str_len)
|
|
474 {
|
|
475 switch(decode_step)
|
|
476 {
|
|
477 case 2:
|
|
478 pProfessions[i].uHirePrice = atoi(test_string);
|
|
479 break;
|
|
480 case 3:
|
|
481 pProfessions[i].pActionText = RemoveQuotes(test_string);
|
|
482 break;
|
|
483 case 4:
|
|
484 pProfessions[i].pBenefits= RemoveQuotes(test_string);
|
|
485 break;
|
|
486 case 5:
|
|
487 pProfessions[i].pJoinText = RemoveQuotes(test_string);
|
|
488 break;
|
|
489 case 6:
|
|
490 pProfessions[i].pDismissText = RemoveQuotes(test_string);
|
|
491 }
|
251
|
492 }
|
291
|
493 else
|
|
494 {
|
570
|
495 if (decode_step)
|
291
|
496 break_loop = true;
|
|
497 }
|
|
498 ++decode_step;
|
|
499 test_string=tmp_pos+1;
|
|
500 } while ((decode_step<7)&&!break_loop);
|
251
|
501 }
|
291
|
502 uNumNPCProfessions = 59;
|
251
|
503 }
|
|
504
|
|
505 //----- (00477266) --------------------------------------------------------
|
|
506 void NPCStats::Release()
|
|
507 {
|
291
|
508 pAllocator->FreeChunk(pNPCTopicTXT_Raw);
|
|
509 pNPCTopicTXT_Raw = NULL;
|
|
510 pAllocator->FreeChunk(pNPCTextTXT_Raw);
|
|
511 pNPCTextTXT_Raw = NULL;
|
|
512 pAllocator->FreeChunk(pNPCNewsTXT_Raw);
|
|
513 pNPCNewsTXT_Raw = NULL;
|
|
514 pAllocator->FreeChunk(pNPCProfTXT_Raw);
|
|
515 pNPCProfTXT_Raw = NULL;
|
|
516 pAllocator->FreeChunk(pNPCNamesTXT_Raw);
|
|
517 pNPCNamesTXT_Raw = NULL;
|
|
518 pAllocator->FreeChunk(pNPCDataTXT_Raw);
|
|
519 pNPCDataTXT_Raw = NULL;
|
|
520 pAllocator->FreeChunk(pNPCDistTXT_Raw);
|
|
521 pNPCDistTXT_Raw = NULL;
|
|
522 pAllocator->FreeChunk(pNPCGreetTXT_Raw);
|
|
523 pNPCGreetTXT_Raw = NULL;
|
|
524 pAllocator->FreeChunk(pNCPGroupTXT_Raw);
|
|
525 pNCPGroupTXT_Raw = NULL;
|
251
|
526 }
|
|
527
|
|
528 //----- (0047730C) --------------------------------------------------------
|
307
|
529 bool CheckPortretAgainstSex(int a1, int)
|
251
|
530 {
|
291
|
531 return true;
|
251
|
532 }
|
|
533 // 47730C: using guessed type int __stdcall const_1(int);
|
|
534
|
|
535 //----- (0047732C) --------------------------------------------------------
|
291
|
536 void NPCStats::InitializeAdditionalNPCs(NPCData *pNPCDataBuff, int npc_uid, int uLocation2D, int uMapId)
|
251
|
537 {
|
292
|
538 int rep_gen;
|
291
|
539 int uNPCSex; // esi@1
|
|
540 int uGeneratedPortret; // ecx@23
|
|
541 int test_prof_summ; // ecx@37
|
|
542 int gen_profession; // eax@37
|
|
543 int max_prof_cap; // edx@37
|
251
|
544 signed int result; // eax@39
|
291
|
545 int uRace; // [sp+Ch] [bp-Ch]@1
|
|
546 bool break_gen; // [sp+10h] [bp-8h]@1
|
|
547 signed int gen_attempts; // [sp+14h] [bp-4h]@1
|
|
548 int uPortretMin; // [sp+24h] [bp+Ch]@1
|
|
549 int uPortretMax;
|
|
550
|
|
551 static const unsigned __int8 NPCSexGenTable[86] ={
|
293
|
552 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
553 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
|
554 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0,
|
|
555 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
556 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 };
|
|
557 static const unsigned __int8 NPCRaceGenTable[86] ={
|
|
558 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 1,
|
|
559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
560 0, 0, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
|
|
561 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
562 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0, 0, 0};
|
251
|
563
|
307
|
564 unsigned __int8 seed = (unsigned __int8)((double)(npc_uid - 1)/3.0);
|
291
|
565 uNPCSex = NPCSexGenTable[seed];
|
|
566 uRace = NPCRaceGenTable[seed];
|
|
567 pNPCDataBuff->uSex = uNPCSex;
|
|
568 pNPCDataBuff->pName = pNPCNames[rand() % uNumNPCNames[uNPCSex]][uNPCSex];
|
|
569
|
|
570 gen_attempts = 0;
|
|
571 break_gen = false;
|
251
|
572
|
291
|
573 do
|
251
|
574 {
|
293
|
575 switch ( uRace )
|
|
576 {
|
|
577 case 0:
|
|
578 if ( uNPCSex == 0 )
|
291
|
579 {
|
|
580 uPortretMin = 2;
|
|
581 uPortretMax = 100;
|
251
|
582 }
|
|
583 else
|
|
584 {
|
293
|
585 uPortretMin = 201;
|
|
586 uPortretMax = 250;
|
|
587 }
|
|
588 case 1:
|
|
589 if ( uNPCSex == 0 )
|
|
590 {
|
|
591 uPortretMin = 400;
|
|
592 uPortretMax = 430;
|
|
593 }
|
|
594 else
|
|
595 {
|
|
596 uPortretMin = 460;
|
|
597 uPortretMax = 490;
|
|
598 }
|
|
599 break;
|
|
600 case 2:
|
|
601 if ( uNPCSex == 0 )
|
|
602 {
|
|
603 uPortretMin = 500;
|
|
604 uPortretMax = 520;
|
|
605 }
|
|
606 else
|
|
607 {
|
|
608 uPortretMin = 530;
|
|
609 uPortretMax = 550;
|
|
610 }
|
|
611 break;
|
|
612 case 3:
|
|
613 if ( uNPCSex == 0 )
|
|
614 {
|
|
615 uPortretMin = 300;
|
|
616 uPortretMax = 330;
|
|
617 }
|
|
618 else
|
|
619 {
|
|
620 uPortretMin = 360;
|
|
621 uPortretMax = 387;
|
251
|
622 }
|
291
|
623
|
293
|
624 break;
|
|
625 }
|
|
626
|
291
|
627 uGeneratedPortret = uPortretMin + rand() % (uPortretMax - uPortretMin + 1);
|
307
|
628 if ( CheckPortretAgainstSex(uGeneratedPortret, uNPCSex))
|
291
|
629 break_gen = true;
|
|
630 ++gen_attempts;
|
|
631 if ( gen_attempts >= 4 )
|
251
|
632 {
|
291
|
633 uGeneratedPortret = uPortretMin;
|
|
634 break_gen = true;
|
251
|
635 }
|
|
636 }
|
291
|
637 while(!break_gen);
|
251
|
638
|
293
|
639 pNPCDataBuff->uPortraitID = uGeneratedPortret;
|
|
640 pNPCDataBuff->uFlags = 0;
|
|
641 pNPCDataBuff->fame = 0;
|
|
642 //generate reputation
|
|
643 rep_gen = rand() % 100 + 1;
|
251
|
644
|
293
|
645 if ( rep_gen >= 60 )
|
251
|
646 {
|
293
|
647 if ( rep_gen >= 90 )
|
251
|
648 {
|
293
|
649 if ( rep_gen >= 95 )
|
|
650 {
|
|
651 if ( rep_gen >= 98 )
|
|
652 pNPCDataBuff->rep = -600;
|
|
653 else
|
|
654 pNPCDataBuff->rep = 400;
|
|
655 }
|
251
|
656 else
|
293
|
657 pNPCDataBuff->rep = -300;
|
251
|
658 }
|
|
659 else
|
293
|
660 pNPCDataBuff->rep = 200;
|
251
|
661 }
|
|
662 else
|
293
|
663 pNPCDataBuff->rep = 0;
|
291
|
664
|
293
|
665 max_prof_cap = rand() % pProfessionChance[uMapId].uTotalprofChance+1;
|
|
666 test_prof_summ = 0;
|
|
667 gen_profession = 0;
|
251
|
668
|
293
|
669 if ( max_prof_cap > 0 )
|
|
670 {
|
|
671 do
|
|
672 test_prof_summ += pProfessionChance[uMapId].professionChancePerArea[gen_profession++];
|
|
673 while ( test_prof_summ < max_prof_cap );
|
|
674 }
|
|
675 pNPCDataBuff->uProfession = gen_profession - 1;
|
|
676 pNPCDataBuff->Location2D = uLocation2D;
|
|
677 pNPCDataBuff->field_24 = 1;
|
|
678 pNPCDataBuff->joins = 1;
|
659
|
679 pNPCDataBuff->evt_A = 0;
|
|
680 pNPCDataBuff->evt_B = 0;
|
|
681 pNPCDataBuff->evt_C = 0;
|
|
682 pNPCDataBuff->evt_D = 0;
|
|
683 pNPCDataBuff->evt_E = 0;
|
|
684 pNPCDataBuff->evt_F = 0;
|
251
|
685 }
|
|
686
|
257
|
687 //----- (00476387) --------------------------------------------------------
|
|
688 bool PartyHasDragon()
|
|
689 {
|
|
690 return pNPCStats->pNewNPCData[57].Hired();
|
|
691 }
|
251
|
692
|
|
693 //----- (00476395) --------------------------------------------------------
|
|
694 //0x26 Wizard eye at skill level 2
|
|
695 bool __thiscall CheckHiredNPCSpeciality(unsigned int uProfession)
|
353
|
696 {
|
251
|
697 bool result; // eax@2
|
|
698 signed int v2; // esi@3
|
|
699 char *v3; // eax@4
|
|
700
|
|
701 if ( bNoNPCHiring == 1 )
|
|
702 return 0;
|
|
703 v2 = 0;
|
|
704 if ( (signed int)pNPCStats->uNumNewNPCs <= 0 )
|
|
705 {
|
|
706 LABEL_8:
|
|
707 result = 0;
|
|
708 if ( pParty->pHirelings[0].uProfession != uProfession )
|
|
709 {
|
|
710 LOBYTE(result) = pParty->pHirelings[1].uProfession == uProfession;
|
|
711 return result;
|
|
712 }
|
|
713 }
|
|
714 else
|
|
715 {
|
|
716 v3 = (char *)&pNPCStats->pNewNPCData[0].uFlags;
|
|
717 while ( *((int *)v3 + 4) != uProfession || !(*v3 & 0x80) )
|
|
718 {
|
|
719 ++v2;
|
|
720 v3 += 76;
|
|
721 if ( v2 >= (signed int)pNPCStats->uNumNewNPCs )
|
|
722 goto LABEL_8;
|
|
723 }
|
|
724 result = 0;
|
|
725 }
|
|
726 ++result;
|
|
727 return result;
|
|
728 }
|
|
729 // 6BE3C5: using guessed type char bNoNPCHiring;
|
|
730
|
|
731 //----- (004763E0) --------------------------------------------------------
|
|
732 void InitializeAwards()
|
|
733 {
|
|
734
|
|
735 int i;
|
|
736 char* test_string;
|
|
737 unsigned char c;
|
|
738 bool break_loop;
|
|
739 unsigned int temp_str_len;
|
|
740 char* tmp_pos;
|
|
741 int decode_step;
|
|
742
|
|
743 if ( pAwardsTXT_Raw )
|
|
744 pAllocator->FreeChunk(pAwardsTXT_Raw);
|
|
745 pAwardsTXT_Raw = NULL;
|
|
746 pAwardsTXT_Raw = (char *)pEvents_LOD->LoadRaw("awards.txt", 0);
|
|
747 strtok(pAwardsTXT_Raw, "\r");
|
|
748
|
|
749 for (i=1; i<104; ++i)
|
|
750 {
|
|
751 test_string = strtok(NULL, "\r") + 1;
|
|
752 break_loop = false;
|
|
753 decode_step=0;
|
|
754 do
|
|
755 {
|
|
756 c = *(unsigned char*)test_string;
|
|
757 temp_str_len = 0;
|
|
758 while((c!='\t')&&(c>0))
|
|
759 {
|
|
760 ++temp_str_len;
|
|
761 c=test_string[temp_str_len];
|
|
762 }
|
|
763 tmp_pos=test_string+temp_str_len;
|
|
764 if (*tmp_pos == 0)
|
|
765 break_loop = true;
|
|
766 *tmp_pos = 0;
|
|
767 if (temp_str_len)
|
|
768 {
|
|
769 if (decode_step==1)
|
|
770 pAwards[i].pText=RemoveQuotes(test_string);
|
|
771 else if (decode_step==2)
|
|
772 pAwards[i].uSort=atoi(test_string);
|
|
773 }
|
|
774 else
|
|
775 {
|
|
776 break_loop = true;
|
|
777 }
|
|
778 ++decode_step;
|
|
779 test_string=tmp_pos+1;
|
|
780 } while ((decode_step<3)&&!break_loop);
|
|
781 }
|
|
782
|
|
783 }
|
|
784 // 7241C8: using guessed type int dword_7241C8;
|
|
785
|
|
786 //----- (004764C2) --------------------------------------------------------
|
|
787 void InitializeScrolls()
|
|
788 {
|
|
789
|
|
790 int i;
|
|
791 char* test_string;
|
|
792 unsigned char c;
|
|
793 bool break_loop;
|
|
794 unsigned int temp_str_len;
|
|
795 char* tmp_pos;
|
|
796 int decode_step;
|
|
797
|
|
798 if ( pScrollsTXT_Raw )
|
|
799 pAllocator->FreeChunk(pScrollsTXT_Raw);
|
|
800 pScrollsTXT_Raw = NULL;
|
|
801 pScrollsTXT_Raw = (char *)pEvents_LOD->LoadRaw("scroll.txt", 0);
|
|
802 strtok(pScrollsTXT_Raw, "\r");
|
|
803 for (i=0; i<82; ++i)
|
|
804 {
|
|
805 test_string = strtok(NULL, "\r") + 1;
|
|
806 break_loop = false;
|
|
807 decode_step=0;
|
|
808 do
|
|
809 {
|
|
810 c = *(unsigned char*)test_string;
|
|
811 temp_str_len = 0;
|
|
812 while((c!='\t')&&(c>0))
|
|
813 {
|
|
814 ++temp_str_len;
|
|
815 c=test_string[temp_str_len];
|
|
816 }
|
|
817 tmp_pos=test_string+temp_str_len;
|
|
818 if (*tmp_pos == 0)
|
|
819 break_loop = true;
|
|
820 *tmp_pos = 0;
|
|
821 if (temp_str_len)
|
|
822 {
|
|
823 if ( decode_step == 1)
|
|
824 pScrolls[i]=RemoveQuotes(test_string);
|
|
825 }
|
|
826 else
|
|
827 {
|
|
828 break_loop = true;
|
|
829 }
|
|
830 ++decode_step;
|
|
831 test_string=tmp_pos+1;
|
|
832 } while ((decode_step<2)&&!break_loop);
|
|
833 }
|
|
834 }
|
|
835
|
|
836 //----- (00476590) --------------------------------------------------------
|
|
837 void InitializeMerchants()
|
|
838 {
|
|
839 int i;
|
|
840 char* test_string;
|
|
841 unsigned char c;
|
|
842 bool break_loop;
|
|
843 unsigned int temp_str_len;
|
|
844 char* tmp_pos;
|
|
845 int decode_step;
|
|
846
|
|
847 if ( pMerchantsTXT_Raw )
|
|
848 pAllocator->FreeChunk(pMerchantsTXT_Raw);
|
|
849 pMerchantsTXT_Raw = NULL;
|
|
850 pMerchantsTXT_Raw = (char *)pEvents_LOD->LoadRaw("merchant.txt", 0);
|
|
851 strtok(pMerchantsTXT_Raw, "\r");
|
|
852
|
|
853 for (i=0; i<7; ++i)
|
|
854 {
|
|
855 test_string = strtok(NULL, "\r") + 1;
|
|
856 break_loop = false;
|
|
857 decode_step=0;
|
|
858 do
|
|
859 {
|
|
860 c = *(unsigned char*)test_string;
|
|
861 temp_str_len = 0;
|
|
862 while((c!='\t')&&(c>0))
|
|
863 {
|
|
864 ++temp_str_len;
|
|
865 c=test_string[temp_str_len];
|
|
866 }
|
|
867 tmp_pos=test_string+temp_str_len;
|
|
868 if (*tmp_pos == 0)
|
|
869 break_loop = true;
|
|
870 *tmp_pos = 0;
|
|
871 if (temp_str_len)
|
|
872 {
|
|
873 switch (decode_step)
|
|
874 {
|
|
875 case 1:
|
|
876 pMerchantsBuyPhrases[i]=RemoveQuotes(test_string);
|
|
877 break;
|
|
878 case 2:
|
|
879 pMerchantsSellPhrases[i]=RemoveQuotes(test_string);
|
|
880 break;
|
|
881 case 3:
|
|
882 pMerchantsRepairPhrases[i]=RemoveQuotes(test_string);
|
|
883 break;
|
|
884 case 4:
|
|
885 pMerchantsIdentifyPhrases[i]=RemoveQuotes(test_string);
|
|
886 break;
|
|
887 }
|
|
888 }
|
|
889 else
|
|
890 {
|
|
891 break_loop = true;
|
|
892 }
|
|
893 ++decode_step;
|
|
894 test_string=tmp_pos+1;
|
|
895 } while ((decode_step<5)&&!break_loop);
|
|
896 }
|
|
897
|
|
898 }
|
|
899
|
|
900 //----- (00476682) --------------------------------------------------------
|
|
901 void InitializeTransitions()
|
|
902 {
|
|
903 int i;
|
|
904 char* test_string;
|
|
905 unsigned char c;
|
|
906 bool break_loop;
|
|
907 unsigned int temp_str_len;
|
|
908 char* tmp_pos;
|
|
909 int decode_step;
|
|
910
|
|
911 if ( pTransitionsTXT_Raw )
|
|
912 pAllocator->FreeChunk(pTransitionsTXT_Raw);
|
|
913 pTransitionsTXT_Raw = NULL;
|
|
914 pTransitionsTXT_Raw = (char *)pEvents_LOD->LoadRaw("trans.txt", 0);
|
|
915 strtok(pTransitionsTXT_Raw, "\r");
|
|
916
|
|
917 for (i=0; i<464; ++i)
|
|
918 {
|
|
919 test_string = strtok(NULL, "\r") + 1;
|
|
920 break_loop = false;
|
|
921 decode_step=0;
|
|
922 do
|
|
923 {
|
|
924 c = *(unsigned char*)test_string;
|
|
925 temp_str_len = 0;
|
|
926 while((c!='\t')&&(c>0))
|
|
927 {
|
|
928 ++temp_str_len;
|
|
929 c=test_string[temp_str_len];
|
|
930 }
|
|
931 tmp_pos=test_string+temp_str_len;
|
|
932 if (*tmp_pos == 0)
|
|
933 break_loop = true;
|
|
934 *tmp_pos = 0;
|
|
935 if (temp_str_len)
|
|
936 {
|
|
937 if ( decode_step == 1)
|
434
|
938 pTransitionStrings[i + 1]=RemoveQuotes(test_string);
|
251
|
939 }
|
|
940 else
|
|
941 {
|
|
942 break_loop = true;
|
|
943 }
|
|
944 ++decode_step;
|
|
945 test_string=tmp_pos+1;
|
|
946 } while ((decode_step<2)&&!break_loop);
|
|
947 }
|
|
948 }
|
|
949
|
|
950 //----- (00476750) --------------------------------------------------------
|
|
951 void __cdecl InitializeAutonotes()
|
|
952 {
|
|
953 int i;
|
|
954 char* test_string;
|
|
955 unsigned char c;
|
|
956 bool break_loop;
|
|
957 unsigned int temp_str_len;
|
|
958 char* tmp_pos;
|
|
959 int decode_step;
|
|
960
|
|
961 if ( pAutonoteTXT_Raw )
|
|
962 pAllocator->FreeChunk(pAutonoteTXT_Raw);
|
|
963 pAutonoteTXT_Raw = 0;
|
|
964 pAutonoteTXT_Raw = (char *)pEvents_LOD->LoadRaw("autonote.txt", 0);
|
|
965 strtok(pAutonoteTXT_Raw, "\r");
|
|
966
|
|
967 for (i=0; i<195; ++i)
|
|
968 {
|
|
969 test_string = strtok(NULL, "\r") + 1;
|
|
970 break_loop = false;
|
|
971 decode_step=0;
|
|
972 do
|
|
973 {
|
|
974 c = *(unsigned char*)test_string;
|
|
975 temp_str_len = 0;
|
|
976 while((c!='\t')&&(c>0))
|
|
977 {
|
|
978 ++temp_str_len;
|
|
979 c=test_string[temp_str_len];
|
|
980 }
|
|
981 tmp_pos=test_string+temp_str_len;
|
|
982 if (*tmp_pos == 0)
|
|
983 break_loop = true;
|
|
984 *tmp_pos = 0;
|
|
985 if (temp_str_len)
|
|
986 {
|
|
987 switch (decode_step)
|
|
988 {
|
|
989 case 1:
|
|
990 pAutonoteTxt[i].pText=RemoveQuotes(test_string);
|
|
991 break;
|
|
992 case 2:
|
|
993 {
|
|
994 if ( !_strcmpi(test_string, "potion"))
|
|
995 {
|
|
996 pAutonoteTxt[i].eType = AUTONOTE_POTION_RECEPIE;
|
|
997 break;
|
|
998 }
|
|
999 if ( !_strcmpi(test_string, "stat") )
|
|
1000 {
|
|
1001 pAutonoteTxt[i].eType = AUTONOTE_STAT_HINT;
|
|
1002 break;
|
|
1003 }
|
|
1004 if ( !_strcmpi(test_string, "seer") )
|
|
1005 {
|
|
1006 pAutonoteTxt[i].eType = AUTONOTE_SEER;
|
|
1007 break;
|
|
1008 }
|
|
1009 if ( !_strcmpi(test_string, "obelisk") )
|
|
1010 {
|
|
1011 pAutonoteTxt[i].eType = AUTONOTE_OBELISK;
|
|
1012 break;
|
|
1013 }
|
|
1014 if ( !_strcmpi(test_string, "teacher") )
|
|
1015 {
|
|
1016 pAutonoteTxt[i].eType = AUTONOTE_TEACHER;
|
|
1017 break;
|
|
1018 }
|
|
1019 pAutonoteTxt[i].eType =AUTONOTE_MISC;
|
|
1020 break;
|
|
1021 }
|
|
1022 }
|
|
1023 }
|
|
1024 else
|
|
1025 {
|
|
1026 break_loop = true;
|
|
1027 }
|
|
1028 ++decode_step;
|
|
1029 test_string=tmp_pos+1;
|
|
1030 } while ((decode_step<3)&&!break_loop);
|
|
1031 }
|
|
1032 }
|
|
1033
|
|
1034
|
|
1035 //----- (004768A9) --------------------------------------------------------
|
|
1036 void __cdecl InitializeQuests()
|
|
1037 {
|
|
1038 int i;
|
|
1039 char* test_string;
|
|
1040 unsigned char c;
|
|
1041 bool break_loop;
|
|
1042 unsigned int temp_str_len;
|
|
1043 char* tmp_pos;
|
|
1044 int decode_step;
|
|
1045
|
|
1046 if ( pQuestsTXT_Raw )
|
|
1047 pAllocator->FreeChunk(pQuestsTXT_Raw);
|
|
1048 pQuestsTXT_Raw = NULL;
|
|
1049 pQuestsTXT_Raw = (char *)pEvents_LOD->LoadRaw("quests.txt", 0);
|
|
1050 strtok(pQuestsTXT_Raw, "\r");
|
|
1051
|
|
1052 for (i=0; i<512; ++i)
|
|
1053 {
|
|
1054 test_string = strtok(NULL, "\r") + 1;
|
|
1055 break_loop = false;
|
|
1056 decode_step=0;
|
|
1057 do
|
|
1058 {
|
|
1059 c = *(unsigned char*)test_string;
|
|
1060 temp_str_len = 0;
|
|
1061 while((c!='\t')&&(c>0))
|
|
1062 {
|
|
1063 ++temp_str_len;
|
|
1064 c=test_string[temp_str_len];
|
|
1065 }
|
|
1066 tmp_pos=test_string+temp_str_len;
|
|
1067 if (*tmp_pos == 0)
|
|
1068 break_loop = true;
|
|
1069 *tmp_pos = 0;
|
|
1070 if (temp_str_len)
|
|
1071 {
|
|
1072 if ( decode_step == 1)
|
|
1073 pQuestTable[i] =RemoveQuotes(test_string);
|
|
1074 }
|
|
1075 else
|
|
1076 {
|
|
1077 break_loop = true;
|
|
1078 }
|
|
1079 ++decode_step;
|
|
1080 test_string=tmp_pos+1;
|
|
1081 } while ((decode_step<2)&&!break_loop);
|
|
1082 }
|
|
1083 }
|
|
1084
|