1 /* GemRB - Infinity Engine Emulator
2  * Copyright (C) 2003 The GemRB Project
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  *
19  */
20 
21 #include "WorldMap.h"
22 
23 #include "Game.h"
24 #include "Interface.h"
25 #include "TableMgr.h"
26 #include "Video.h"
27 #include "RNG.h"
28 
29 #include <list>
30 
31 namespace GemRB {
32 
WMPAreaEntry()33 WMPAreaEntry::WMPAreaEntry()
34 {
35 	MapIcon = NULL;
36 	StrCaption = NULL;
37 	StrTooltip = NULL;
38 	SingleFrame = false;
39 	AreaName[0] = AreaLongName[0] = AreaResRef[0] = 0;
40 	LoadScreenResRef[0] = 0;
41 	LocCaptionName = LocTooltipName = 0;
42 	AreaLinksCount[0] = AreaLinksIndex[0] = 0;
43 	IconSeq = AreaStatus = 0;
44 }
45 
~WMPAreaEntry()46 WMPAreaEntry::~WMPAreaEntry()
47 {
48 	delete StrCaption;
49 	free(StrTooltip);
50 }
51 
SetAreaStatus(ieDword arg,int op)52 void WMPAreaEntry::SetAreaStatus(ieDword arg, int op)
53 {
54 	SetBits(AreaStatus, arg, op);
55 	MapIcon = nullptr;
56 }
57 
GetCaption()58 const String* WMPAreaEntry::GetCaption()
59 {
60 	if (!StrCaption) {
61 		StrCaption = core->GetString(LocCaptionName);
62 	}
63 	return StrCaption;
64 }
65 
GetTooltip()66 const char* WMPAreaEntry::GetTooltip()
67 {
68 	if (!StrTooltip) {
69 		StrTooltip = core->GetCString(LocTooltipName);
70 	}
71 	return StrTooltip;
72 }
73 
GetMapIcon(const AnimationFactory * bam)74 Holder<Sprite2D> WMPAreaEntry::GetMapIcon(const AnimationFactory *bam)
75 {
76 	if (!bam || IconSeq == (ieDword) -1) {
77 		return NULL;
78 	}
79 	if (!MapIcon) {
80 		int frame = 0;
81 		switch (AreaStatus&(WMP_ENTRY_ACCESSIBLE|WMP_ENTRY_VISITED))
82 		{
83 			case WMP_ENTRY_ACCESSIBLE: frame = 0; break;
84 			case WMP_ENTRY_VISITED: frame = 4; break;
85 			case WMP_ENTRY_ACCESSIBLE|WMP_ENTRY_VISITED: frame = 1; break;
86 			case 0: frame = 2; break;
87 		}
88 
89 		// iwd1, bg1 and pst all have this format
90 		if (bam->GetCycleSize(IconSeq)<5) {
91 			SingleFrame = true;
92 			frame = 0;
93 		}
94 		MapIcon = bam->GetFrame((ieWord) frame, (ieByte) IconSeq);
95 		if (!MapIcon) {
96 			Log(ERROR, "WMPAreaEntry", "GetMapIcon failed for frame %d, seq %d", frame, IconSeq);
97 			return NULL;
98 		}
99 	}
100 	return MapIcon;
101 }
102 
GetAreaStatus()103 ieDword WMPAreaEntry::GetAreaStatus()
104 {
105 	ieDword tmp = AreaStatus;
106 	if (core->HasFeature(GF_KNOW_WORLD) ) {
107 		tmp |=WMP_ENTRY_VISITED;
108 	}
109 	return tmp;
110 }
111 
WorldMap(void)112 WorldMap::WorldMap(void)
113 {
114 	MapMOS = NULL;
115 	Distances = NULL;
116 	GotHereFrom = NULL;
117 	bam = NULL;
118 	encounterArea = -1;
119 	Width = Height = 0;
120 	MapNumber = AreaName = 0;
121 	Flags = 0;
122 	unknown1 = unknown2 = 0;
123 }
124 
125 //Allocate AE and AL only in Core, otherwise Win32 will
126 //be buggy
AddAreaEntry(WMPAreaEntry * ae)127 void WorldMap::AddAreaEntry(WMPAreaEntry *ae)
128 {
129 	area_entries.push_back(ae);
130 }
131 
AddAreaLink(WMPAreaLink * al)132 void WorldMap::AddAreaLink(WMPAreaLink *al)
133 {
134 	area_links.push_back(al);
135 }
136 
GetNewAreaEntry() const137 WMPAreaEntry *WorldMap::GetNewAreaEntry() const
138 {
139 	return new WMPAreaEntry();
140 }
141 
SetAreaEntry(unsigned int x,WMPAreaEntry * ae)142 void WorldMap::SetAreaEntry(unsigned int x, WMPAreaEntry *ae)
143 {
144 	//if index is too large, we break
145 	if (x>area_entries.size()) {
146 		error("WorldMap", "Trying to set invalid entry (%d/%d)\n", x, (int)area_entries.size());
147 	}
148 	//altering an existing entry
149 	if (x<area_entries.size()) {
150 		if (area_entries[x]) {
151 			delete area_entries[x];
152 		}
153 		area_entries[x]=ae;
154 		return;
155 	}
156 	//adding a new entry
157 	area_entries.push_back(ae);
158 }
159 
InsertAreaLink(unsigned int areaidx,unsigned int dir,WMPAreaLink * arealink)160 void WorldMap::InsertAreaLink(unsigned int areaidx, unsigned int dir, WMPAreaLink *arealink)
161 {
162 	unsigned int pos;
163 	WMPAreaEntry *ae;
164 
165 	WMPAreaLink *al = new WMPAreaLink();
166 	memcpy(al, arealink, sizeof(WMPAreaLink) );
167 	unsigned int idx = area_entries[areaidx]->AreaLinksIndex[dir];
168 	area_links.insert(area_links.begin()+idx,al);
169 
170 	unsigned int max = area_entries.size();
171 	for(pos = 0; pos<max; pos++) {
172 		ae = area_entries[pos];
173 		for (unsigned int k=0;k<4;k++) {
174 			if ((pos==areaidx) && (k==dir)) {
175 				ae->AreaLinksCount[k]++;
176 				continue;
177 			}
178 			if(ae->AreaLinksIndex[k]>=idx) {
179 				ae->AreaLinksIndex[k]++;
180 			}
181 		}
182 	}
183 }
184 
SetAreaLink(unsigned int x,WMPAreaLink * arealink)185 void WorldMap::SetAreaLink(unsigned int x, WMPAreaLink *arealink)
186 {
187 	WMPAreaLink *al =new WMPAreaLink();
188 
189 	//change this to similar code as above if WMPAreaLink gets non-struct members
190 	memcpy( al,arealink,sizeof(WMPAreaLink) );
191 
192 	//if index is too large, we break
193 	if (x>area_links.size()) {
194 		error("WorldMap", "Trying to set invalid link (%d/%d)", x, (int)area_links.size());
195 	}
196 	//altering an existing link
197 	if (x<area_links.size()) {
198 		if (area_links[x]) {
199 			delete area_links[x];
200 		}
201 		area_links[x]=al;
202 		return;
203 	}
204 	//adding a new link
205 	area_links.push_back(al);
206 }
207 
~WorldMap(void)208 WorldMap::~WorldMap(void)
209 {
210 	unsigned int i;
211 
212 	for (i = 0; i < area_entries.size(); i++) {
213 		delete( area_entries[i] );
214 	}
215 	for (i = 0; i < area_links.size(); i++) {
216 		delete( area_links[i] );
217 	}
218 	if (Distances) {
219 		free(Distances);
220 	}
221 	if (GotHereFrom) {
222 		free(GotHereFrom);
223 	}
224 	if (bam) bam = NULL;
225 }
226 
SetMapIcons(AnimationFactory * newicons)227 void WorldMap::SetMapIcons(AnimationFactory *newicons)
228 {
229 	bam = newicons;
230 }
231 
SetMapMOS(Holder<Sprite2D> newmos)232 void WorldMap::SetMapMOS(Holder<Sprite2D> newmos)
233 {
234 	MapMOS = newmos;
235 }
236 
GetArea(const ieResRef AreaName,unsigned int & i) const237 WMPAreaEntry* WorldMap::GetArea(const ieResRef AreaName, unsigned int &i) const
238 {
239 	i=(unsigned int) area_entries.size();
240 	while (i--) {
241 		if (!strnicmp(AreaName, area_entries[i]->AreaName,8)) {
242 			return area_entries[i];
243 		}
244 	}
245 	return NULL;
246 }
247 
248 //Find Worldmap location by nearest area with a smaller number
249 //Counting backwards, stop at 1000 boundaries.
250 //It is not possible to simply round to 1000, because there are
251 //WMP entries like AR8001, and we need to find the best match
FindNearestEntry(const ieResRef AreaName,unsigned int & i) const252 WMPAreaEntry* WorldMap::FindNearestEntry(const ieResRef AreaName, unsigned int &i) const
253 {
254 	int value = 0;
255 	ieResRef tmp;
256 
257 	sscanf(&AreaName[2],"%4d", &value);
258 	do {
259 		snprintf(tmp, 9, "%.2s%04d", AreaName, value);
260 		WMPAreaEntry* ret = GetArea(tmp, i);
261 		if (ret) {
262 			return ret;
263 		}
264 		if (value%1000 == 0) break;
265 		value--;
266 	}
267 	while(1); //value%1000 should protect us from infinite loops
268 	i = -1;
269 	return NULL;
270 }
271 
272 //this is a pathfinding algorithm
273 //you have to find the optimal path
CalculateDistances(const ieResRef AreaName,int direction)274 int WorldMap::CalculateDistances(const ieResRef AreaName, int direction)
275 {
276 	//first, update reachable/visible areas by worlde.2da if exists
277 	UpdateReachableAreas();
278 	UpdateAreaVisibility(AreaName, direction);
279 	if (direction==-1) {
280 		return 0;
281 	}
282 
283 	if (direction<0 || direction>3) {
284 		Log(ERROR, "WorldMap", "CalculateDistances for invalid direction: %s", AreaName);
285 		return -1;
286 	}
287 
288 	unsigned int i;
289 	if (!GetArea(AreaName, i)) {
290 		Log(ERROR, "WorldMap", "CalculateDistances for invalid Area: %s", AreaName);
291 		return -1;
292 	}
293 	if (Distances) {
294 		free(Distances);
295 	}
296 	if (GotHereFrom) {
297 		free(GotHereFrom);
298 	}
299 
300 	Log(MESSAGE, "WorldMap", "CalculateDistances for Area: %s", AreaName);
301 
302 	size_t memsize =sizeof(int) * area_entries.size();
303 	Distances = (int *) malloc( memsize );
304 	GotHereFrom = (int *) malloc( memsize );
305 	memset( Distances, -1, memsize );
306 	memset( GotHereFrom, -1, memsize );
307 	Distances[i] = 0; //setting our own distance
308 	GotHereFrom[i] = -1; //we didn't move
309 
310 	int *seen_entry = (int *) malloc( memsize );
311 
312 	std::list<int> pending;
313 	pending.push_back(i);
314 	while(!pending.empty()) {
315 		i=pending.front();
316 		pending.pop_front();
317 		WMPAreaEntry* ae=area_entries[i];
318 		memset( seen_entry, -1, memsize );
319 		//all directions should be used
320 		for(int d=0;d<4;d++) {
321 			int j=ae->AreaLinksIndex[d];
322 			int k=j+ae->AreaLinksCount[d];
323 			if ((size_t) k>area_links.size()) {
324 				Log(ERROR, "WorldMap", "The worldmap file is corrupted... and it would crash right now! Entry #: %d Direction: %d",
325 					i, d);
326 				break;
327 			}
328 			for(;j<k;j++) {
329 				WMPAreaLink* al = area_links[j];
330 				WMPAreaEntry* ae2 = area_entries[al->AreaIndex];
331 				unsigned int mydistance = (unsigned int) Distances[i];
332 
333 				// we must only process the FIRST seen link to each area from this one
334 				if (seen_entry[al->AreaIndex] != -1) continue;
335 				seen_entry[al->AreaIndex] = 0;
336 /*
337 				if ( ( (ae->GetAreaStatus() & WMP_ENTRY_PASSABLE) == WMP_ENTRY_PASSABLE) &&
338 				( (ae2->GetAreaStatus() & WMP_ENTRY_WALKABLE) == WMP_ENTRY_WALKABLE)
339 */
340 				if ( (ae2->GetAreaStatus() & WMP_ENTRY_WALKABLE) == WMP_ENTRY_WALKABLE) {
341 					// al->Flags is the entry direction
342 					mydistance += al->DistanceScale * 4;
343 					//nonexisting distance is the biggest!
344 					if ((unsigned) Distances[al->AreaIndex] > mydistance) {
345 						Distances[al->AreaIndex] = mydistance;
346 						GotHereFrom[al->AreaIndex] = j;
347 						pending.push_back(al->AreaIndex);
348 					}
349 				}
350 			}
351 		}
352 	}
353 
354 	free(seen_entry);
355 	return 0;
356 }
357 
358 //returns the index of the area owning this link
WhoseLinkAmI(int link_index) const359 unsigned int WorldMap::WhoseLinkAmI(int link_index) const
360 {
361 	unsigned int cnt = GetEntryCount();
362 	for (unsigned int i = 0; i < cnt; i++) {
363 		WMPAreaEntry *ae=area_entries[i];
364 		for (int direction=0;direction<4;direction++)
365 		{
366 			int j=ae->AreaLinksIndex[direction];
367 			if (link_index>=j) {
368 				j+=ae->AreaLinksCount[direction];
369 				if(link_index<j) {
370 					return i;
371 				}
372 			}
373 		}
374 	}
375 	return (ieDword) -1;
376 }
377 
GetLink(const ieResRef A,const ieResRef B) const378 WMPAreaLink *WorldMap::GetLink(const ieResRef A, const ieResRef B) const
379 {
380 	unsigned int i,j,k;
381 
382 	WMPAreaEntry *ae=GetArea( A, i );
383 	if (!ae) {
384 		return NULL;
385 	}
386 	//looking for destination area, returning the first link found
387 	for (i=0;i<4;i++) {
388 		j=ae->AreaLinksCount[i];
389 		k=ae->AreaLinksIndex[i];
390 		while(j--) {
391 			WMPAreaLink *al = area_links[k++];
392 			WMPAreaEntry *ae2 = area_entries[al->AreaIndex];
393 			//or arearesref?
394 			if (strnicmp(ae2->AreaName, B, 8)==0) {
395 				return al;
396 			}
397 		}
398 	}
399 	return NULL;
400 }
401 
402 //call this function to find out which area we fall into
403 //not necessarily the target area
404 //if it isn't the same, then a random encounter happened!
GetEncounterLink(const ieResRef AreaName,bool & encounter) const405 WMPAreaLink *WorldMap::GetEncounterLink(const ieResRef AreaName, bool &encounter) const
406 {
407 	if (!GotHereFrom) {
408 		return NULL;
409 	}
410 	unsigned int i;
411 	WMPAreaEntry *ae=GetArea( AreaName, i ); //target area
412 	if (!ae) {
413 		Log(ERROR, "WorldMap", "No such area: %s", AreaName);
414 		return NULL;
415 	}
416 	std::list<WMPAreaLink*> walkpath;
417 	Log(DEBUG, "WorldMap", "Gathering path information for: %s", AreaName);
418 	while (GotHereFrom[i]!=-1) {
419 		Log(DEBUG, "WorldMap", "Adding path to %d", i);
420 		walkpath.push_back(area_links[GotHereFrom[i]]);
421 		i = WhoseLinkAmI(GotHereFrom[i]);
422 		if (i==(ieDword) -1) {
423 			error("WorldMap", "Something has been screwed up here (incorrect path)!\n");
424 		}
425 	}
426 
427 	Log(DEBUG, "WorldMap", "Walkpath size is: %d", (int) walkpath.size());
428 	if (walkpath.empty()) {
429 		return NULL;
430 	}
431 	std::list<WMPAreaLink*>::reverse_iterator p=walkpath.rbegin();
432 	WMPAreaLink *lastpath;
433 	encounter=false;
434 	do {
435 		lastpath = *p;
436 		if (lastpath->EncounterChance > (unsigned int) RAND(0, 99)) {
437 			encounter=true;
438 			break;
439 		}
440 		++p;
441 	}
442 	while(p!=walkpath.rend() );
443 	return lastpath;
444 }
445 
446 //adds a temporary AreaEntry to the world map
447 //this entry has two links for each direction, leading to the two areas
448 //we were travelling between when using the supplied link
SetEncounterArea(const ieResRef area,WMPAreaLink * link)449 void WorldMap::SetEncounterArea(const ieResRef area, WMPAreaLink *link) {
450 	unsigned int i;
451 	if (GetArea(area, i)) {
452 		return;
453 	}
454 
455 	//determine the area the link came from
456 	unsigned int j, cnt = GetLinkCount();
457 	for (j = 0; j < cnt; ++j) {
458 		if (link == area_links[j]) {
459 			break;
460 		}
461 	}
462 
463 	i = WhoseLinkAmI(j);
464 	if (i == (unsigned int) -1) {
465 		Log(ERROR, "WorldMap", "Could not add encounter area");
466 		return;
467 	}
468 
469 	WMPAreaEntry *ae = GetNewAreaEntry();
470 	ae->SetAreaStatus(WMP_ENTRY_VISIBLE|WMP_ENTRY_ACCESSIBLE|WMP_ENTRY_VISITED, OP_SET);
471 	CopyResRef(ae->AreaName, area);
472 	CopyResRef(ae->AreaResRef, area);
473 	ae->LocCaptionName = -1;
474 	ae->LocTooltipName = -1;
475 	ae->IconSeq = -1;
476 	CopyResRef(ae->LoadScreenResRef, "");
477 
478 	WMPAreaEntry *src = area_entries[i];
479 	WMPAreaEntry *dest = area_entries[link->AreaIndex];
480 	ae->pos.x = src->pos.x + (dest->pos.x - src->pos.x) / 2;
481 	ae->pos.y = src->pos.y + (dest->pos.y - src->pos.y) / 2;
482 
483 	//setup the area links
484 	WMPAreaLink *ldest = new WMPAreaLink();
485 	memcpy(ldest, link, sizeof(WMPAreaLink));
486 	ldest->DistanceScale /= 2;
487 	ldest->EncounterChance = 0;
488 
489 	link = GetLink(dest->AreaName, src->AreaName);
490 	if (!link) {
491 		Log(ERROR, "WorldMap", "Could not find link from %s to %s",
492 			dest->AreaName, src->AreaName);
493 		delete ae;
494 		delete ldest;
495 		return;
496 	}
497 
498 	WMPAreaLink *lsrc = new WMPAreaLink();
499 	memcpy(lsrc, link, sizeof(WMPAreaLink));
500 	lsrc->DistanceScale /= 2;
501 	lsrc->EncounterChance = 0;
502 
503 	unsigned int idx = area_links.size();
504 	AddAreaLink(ldest);
505 	AddAreaLink(lsrc);
506 
507 	for (i = 0; i < 4; ++i) {
508 		ae->AreaLinksCount[i] = 2;
509 		ae->AreaLinksIndex[i] = idx;
510 	}
511 
512 	encounterArea = area_entries.size();
513 	AddAreaEntry(ae);
514 }
515 
ClearEncounterArea()516 void WorldMap::ClearEncounterArea()
517 {
518 	if (encounterArea == -1) {
519 		return;
520 	}
521 
522 	WMPAreaEntry *ea = area_entries[encounterArea];
523 	area_entries.erase(area_entries.begin() + encounterArea);
524 
525 	WMPAreaLink *l = area_links[ea->AreaLinksIndex[0]];
526 	delete l;
527 	l = area_links[ea->AreaLinksIndex[0] + 1];
528 	delete l;
529 
530 	//NOTE: if anything else added links after us we'd have to globally
531 	//update all link indices, but since ambush areas do not allow
532 	//saving/loading we should be okay with this
533 	area_links.erase(area_links.begin() + ea->AreaLinksIndex[0],
534 		area_links.begin() + ea->AreaLinksIndex[0] + ea->AreaLinksCount[0]);
535 
536 	delete ea;
537 	encounterArea = -1;
538 }
539 
GetDistance(const ieResRef AreaName) const540 int WorldMap::GetDistance(const ieResRef AreaName) const
541 {
542 	if (!Distances) {
543 		return -1;
544 	}
545 	unsigned int i;
546 	if (GetArea( AreaName, i )) {
547 		return Distances[i];
548 	}
549 	return -1;
550 }
551 
UpdateAreaVisibility(const ieResRef AreaName,int direction)552 void WorldMap::UpdateAreaVisibility(const ieResRef AreaName, int direction)
553 {
554 	unsigned int i;
555 
556 	WMPAreaEntry* ae=GetArea(AreaName,i);
557 	if (!ae)
558 		return;
559 	//we are here, so we visited and it is visible too (i guess)
560 	Log(DEBUG, "WorldMap", "Updated Area visibility: %s (visited, accessible and visible)", AreaName);
561 
562 	ae->SetAreaStatus(WMP_ENTRY_VISITED|WMP_ENTRY_VISIBLE|WMP_ENTRY_ACCESSIBLE, OP_OR);
563 	if (direction<0 || direction>3)
564 		return;
565 	i=ae->AreaLinksCount[direction];
566 	while (i--) {
567 		WMPAreaLink* al = area_links[ae->AreaLinksIndex[direction]+i];
568 		WMPAreaEntry* ae2 = area_entries[al->AreaIndex];
569 		if (ae2->GetAreaStatus()&WMP_ENTRY_ADJACENT) {
570 			Log(DEBUG, "WorldMap", "Updated Area visibility: %s (accessible and visible)", ae2->AreaName);
571 			ae2->SetAreaStatus(WMP_ENTRY_VISIBLE|WMP_ENTRY_ACCESSIBLE, OP_OR);
572 		}
573 	}
574 }
575 
SetAreaStatus(const ieResRef AreaName,int Bits,int Op)576 void WorldMap::SetAreaStatus(const ieResRef AreaName, int Bits, int Op)
577 {
578 	unsigned int i;
579 	WMPAreaEntry* ae=GetArea(AreaName,i);
580 	if (!ae)
581 		return;
582 	ae->SetAreaStatus(Bits, Op);
583 }
584 
UpdateReachableAreas()585 void WorldMap::UpdateReachableAreas()
586 {
587 	AutoTable tab("worlde", true);
588 	if (!tab) {
589 		return;
590 	}
591 	Game *game = core->GetGame();
592 	if (!game) {
593 		return;
594 	}
595 	int idx = tab->GetRowCount();
596 	while (idx--) {
597 		// 2da rows in format <name> <variable name> <area>
598 		// we set the first three flags for <area> if <variable name> is set
599 		ieDword varval = 0;
600 		const char *varname = tab->QueryField(idx, 0);
601 		if (game->locals->Lookup(varname, varval) && varval) {
602 			const char *areaname = tab->QueryField(idx, 1);
603 			SetAreaStatus(areaname, WMP_ENTRY_VISIBLE | WMP_ENTRY_ADJACENT | WMP_ENTRY_ACCESSIBLE, OP_OR);
604 		}
605 	}
606 }
607 
608 /****************** WorldMapArray *******************/
WorldMapArray(unsigned int count)609 WorldMapArray::WorldMapArray(unsigned int count)
610 {
611 	CurrentMap = 0;
612 	MapCount = count;
613 	all_maps = (WorldMap **) calloc(count, sizeof(WorldMap *) );
614 	single = true;
615 }
616 
~WorldMapArray()617 WorldMapArray::~WorldMapArray()
618 {
619 	unsigned int i;
620 
621 	for (i = 0; i<MapCount; i++) {
622 		if (all_maps[i]) {
623 			delete all_maps[i];
624 		}
625 	}
626 	free( all_maps );
627 }
628 
FindAndSetCurrentMap(const ieResRef area)629 unsigned int WorldMapArray::FindAndSetCurrentMap(const ieResRef area)
630 {
631 	unsigned int i, idx;
632 
633 	for (i = CurrentMap; i<MapCount; i++) {
634 		if (all_maps[i]->GetArea (area, idx) ) {
635 			CurrentMap = i;
636 			return i;
637 		}
638 	}
639 	for (i = 0; i<CurrentMap; i++) {
640 		if (all_maps[i]->GetArea (area, idx) ) {
641 			CurrentMap = i;
642 			return i;
643 		}
644 	}
645 	return CurrentMap;
646 }
647 
SetWorldMap(WorldMap * m,unsigned int index)648 void WorldMapArray::SetWorldMap(WorldMap *m, unsigned int index)
649 {
650 	if (index<MapCount) {
651 		all_maps[index]=m;
652 	}
653 }
654 
NewWorldMap(unsigned int index)655 WorldMap *WorldMapArray::NewWorldMap(unsigned int index)
656 {
657 	if (all_maps[index]) {
658 		delete all_maps[index];
659 	}
660 	all_maps[index] = new WorldMap();
661 	return all_maps[index];
662 }
663 
664 }
665