3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
8 * See LICENSING which should be included
9 * along with this file for more details
13 /* Compiled through wmapset.cpp */
15 #define MAX_TEMPERATURE 27 //increase for a warmer world
16 #define LATITUDE_EFFECT 40 //increase for more effect
17 #define ALTITUDE_EFFECT 0.02
24 static const int DirX
[8] = { -1, -1, -1, 0, 0, 1, 1, 1 };
25 static const int DirY
[8] = { -1, 0, 1, -1, 1, -1, 0, 1 };
28 std::vector
<owterrain
*> worldmap::Places
;
29 std::vector
<int> worldmap::PlaceTypes
;
30 std::vector
<int> worldmap::PlaceDungeons
;
31 std::vector
<PlaceSpawner
> worldmap::PlaceSpawners
;
33 worldmap::worldmap () {}
34 continent
*worldmap::GetContinentUnder (v2 Pos
) const { return Continent
[ContinentBuffer
[Pos
.X
][Pos
.Y
]]; }
35 v2
worldmap::GetEntryPos (ccharacter
*, int I
) const { return EntryMap
.find(I
)->second
; }
36 continent
*worldmap::GetContinent (int I
) const { return Continent
[I
]; }
37 int worldmap::GetAltitude (v2 Pos
) { return AltitudeBuffer
[Pos
.X
][Pos
.Y
]; }
38 charactervector
&worldmap::GetPlayerGroup () { return PlayerGroup
; }
39 character
*worldmap::GetPlayerGroupMember (int c
) { return PlayerGroup
[c
]; }
42 worldmap::worldmap (int XSize
, int YSize
) : area(XSize
, YSize
) {
43 Map
= reinterpret_cast<wsquare
***>(area::Map
);
44 for (int x
= 0; x
< XSize
; ++x
) {
45 for (int y
= 0; y
< YSize
; ++y
) {
46 Map
[x
][y
] = new wsquare(this, v2(x
, y
));
47 Map
[x
][y
]->SetGWTerrain(ocean::Spawn());
50 Alloc2D(TypeBuffer
, XSize
, YSize
);
51 Alloc2D(AltitudeBuffer
, XSize
, YSize
);
52 Alloc2D(ContinentBuffer
, XSize
, YSize
);
53 continent::TypeBuffer
= TypeBuffer
;
54 continent::AltitudeBuffer
= AltitudeBuffer
;
55 continent::ContinentBuffer
= ContinentBuffer
;
59 worldmap::~worldmap () {
61 delete [] AltitudeBuffer
;
62 delete [] ContinentBuffer
;
63 for (uInt c
= 1; c
< Continent
.size(); ++c
) delete Continent
[c
];
64 for (uInt c
= 0; c
< PlayerGroup
.size(); ++c
) delete PlayerGroup
[c
];
68 void worldmap::Save (outputfile
&SaveFile
) const {
70 SaveFile
.Write(reinterpret_cast<char*>(TypeBuffer
[0]), XSizeTimesYSize
*sizeof(uChar
));
71 SaveFile
.Write(reinterpret_cast<char*>(AltitudeBuffer
[0]), XSizeTimesYSize
*sizeof(short));
72 SaveFile
.Write(reinterpret_cast<char*>(ContinentBuffer
[0]), XSizeTimesYSize
*sizeof(uChar
));
73 for (feuLong c
= 0; c
< XSizeTimesYSize
; ++c
) Map
[0][c
]->Save(SaveFile
);
74 SaveFile
<< Continent
<< PlayerGroup
;
78 void worldmap::Load (inputfile
&SaveFile
) {
80 Map
= reinterpret_cast<wsquare
***>(area::Map
);
81 Alloc2D(TypeBuffer
, XSize
, YSize
);
82 Alloc2D(AltitudeBuffer
, XSize
, YSize
);
83 Alloc2D(ContinentBuffer
, XSize
, YSize
);
84 SaveFile
.Read(reinterpret_cast<char*>(TypeBuffer
[0]), XSizeTimesYSize
*sizeof(uChar
));
85 SaveFile
.Read(reinterpret_cast<char*>(AltitudeBuffer
[0]), XSizeTimesYSize
*sizeof(short));
86 SaveFile
.Read(reinterpret_cast<char*>(ContinentBuffer
[0]), XSizeTimesYSize
*sizeof(uChar
));
87 continent::TypeBuffer
= TypeBuffer
;
88 continent::AltitudeBuffer
= AltitudeBuffer
;
89 continent::ContinentBuffer
= ContinentBuffer
;
91 for (x
= 0; x
< XSize
; ++x
)
92 for (y
= 0; y
< YSize
; ++y
)
93 Map
[x
][y
] = new wsquare(this, v2(x
, y
));
94 for (x
= 0; x
< XSize
; ++x
) {
95 for (y
= 0; y
< YSize
; ++y
) {
96 game::SetSquareInLoad(Map
[x
][y
]);
97 Map
[x
][y
]->Load(SaveFile
);
100 CalculateNeighbourBitmapPoses();
101 SaveFile
>> Continent
>> PlayerGroup
;
105 void worldmap::Generate () {
106 Alloc2D(OldAltitudeBuffer
, XSize
, YSize
);
107 Alloc2D(OldTypeBuffer
, XSize
, YSize
);
109 //fprintf(stderr, "places: %u\n", Places.size());
112 PlacePosition
.clear();
113 PlaceRevealed
.clear();
114 PlaceContinent
.clear();
115 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
116 PlacePosition
.push_back(ERROR_V2
);
117 PlaceRevealed
.push_back(false);
118 PlaceContinent
.push_back(0);
125 CalculateContinents();
127 std::vector
<continent
*> PerfectForAttnam
, PerfectForNewAttnam
;
128 continent
*PetrusLikes
= 0;
129 int nearPetrusCount
= 0;
131 // find places for attnam
132 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
133 if (Places
[f
]->IsAttnam()) {
134 for (uInt c
= 1; c
< Continent
.size(); ++c
) {
135 if (Places
[f
]->IsSuitableContinent(Continent
[c
])) PerfectForAttnam
.push_back(Continent
[c
]);
137 } else if (Places
[f
]->WantPetrusContinent()) {
141 if (!PerfectForAttnam
.size()) continue;
142 // try to place all 'near petrus' places
143 while (PerfectForAttnam
.size() > 0) {
144 int pno
= RAND()%PerfectForAttnam
.size();
147 PetrusLikes
= PerfectForAttnam
[pno
];
148 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
149 if (!Places
[f
]->IsAttnam() && Places
[f
]->WantPetrusContinent() && Places
[f
]->IsSuitableContinent(PetrusLikes
)) {
153 if (nphit
== nearPetrusCount
) break; // ok
157 if (!PetrusLikes
) continue; // alas
158 //TODO: try non-petrus-wants
160 v2 NewAttnamPos
, TunnelEntry
, TunnelExit
;
161 //v2 AttnamPos, ElpuriCavePos, NewAttnamPos, TunnelEntry, TunnelExit, MondedrPos, MuntuoPos;
162 //v2 DragonTowerPos, DarkForestPos, XinrochTombPos;
163 truth Correct
= false;
164 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
165 if (Places
[f
]->IsAttnam() || Places
[f
]->WantPetrusContinent()) PlacePosition
[f
] = ERROR_V2
;
168 for (int c1
= 0; c1
< 25; ++c1
) {
169 game::BusyAnimation();
171 //PetrusLikes = PerfectForAttnam[RAND() % PerfectForAttnam.size()];
172 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
173 if (Places
[f
]->IsAttnam() || Places
[f
]->WantPetrusContinent()) {
174 truth success
= false;
175 PlacePosition
[f
] = PetrusLikes
->GetRandomMember(PlaceTypes
[f
], &success
);
176 if (!success
) goto allagain
; //FIXME: memory leak
180 for (int c2
= 1; c2
< 50; ++c2
) {
181 truth tunnelExitOkPos
= true;
183 TunnelExit
= PetrusLikes
->GetMember(RAND()%PetrusLikes
->GetSize());
184 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
185 if (PlacePosition
[f
] != ERROR_V2
) {
186 if (PlacePosition
[f
] == TunnelExit
) { tunnelExitOkPos
= false; break; }
189 if (!tunnelExitOkPos
) continue;
191 for (int d1
= 0; d1
< 8; ++d1
) {
192 v2 Pos
= TunnelExit
+game::GetMoveVector(d1
);
194 if (IsValidPos(Pos
) && AltitudeBuffer
[Pos
.X
][Pos
.Y
] <= 0) {
195 int Distance
= 3+(RAND() & 3);
201 for (int c2
= 0; c2
< Distance
; ++c2
) {
202 TunnelEntry
+= game::GetMoveVector(d1
);
203 if (!IsValidPos(TunnelEntry
) || AltitudeBuffer
[TunnelEntry
.X
][TunnelEntry
.Y
] > 0) { Error
= true; break; }
206 for (x
= TunnelEntry
.X
-3; x
<= TunnelEntry
.X
+3; ++x
) {
207 for (y
= TunnelEntry
.Y
-3; y
<= TunnelEntry
.Y
+3; ++y
, ++Counter
) {
208 if (Counter
!= 0 && Counter
!= 6 && Counter
!= 42 && Counter
!= 48 &&
209 (!IsValidPos(x
, y
) || AltitudeBuffer
[x
][y
] > 0 || AltitudeBuffer
[x
][y
] < -350)) {
218 for (x
= 0; x
< XSize
; ++x
) if (TypeBuffer
[x
][TunnelEntry
.Y
] == JungleType
) { Error
= false; break; }
221 for (x
= TunnelEntry
.X
- 2; x
<= TunnelEntry
.X
+2; ++x
) {
222 for (y
= TunnelEntry
.Y
- 2; y
<= TunnelEntry
.Y
+2; ++y
, ++Counter
) {
223 if (Counter
!= 0 && Counter
!= 4 && Counter
!= 20 && Counter
!= 24) AltitudeBuffer
[x
][y
] /= 2;
226 AltitudeBuffer
[TunnelEntry
.X
][TunnelEntry
.Y
] = 1+RAND()%50;
227 TypeBuffer
[TunnelEntry
.X
][TunnelEntry
.Y
] = JungleType
;
228 GetWSquare(TunnelEntry
)->ChangeGWTerrain(jungle::Spawn());
231 for (NewAttnamIndex
= RAND()&7; NewAttnamIndex
== 7-d1
; NewAttnamIndex
= RAND()&7) ;
232 NewAttnamPos
= TunnelEntry
+game::GetMoveVector(NewAttnamIndex
);
234 static const int DiagonalDir
[4] = { 0, 2, 5, 7 };
235 static const int NotDiagonalDir
[4] = { 1, 3, 4, 6 };
236 static const int AdjacentDir
[4][2] = { { 0, 1 }, { 0, 2 }, { 1, 3 }, { 2, 3 } };
237 truth Raised
[] = { false, false, false, false };
239 for (int d2
= 0; d2
< 4; ++d2
) {
240 if (NotDiagonalDir
[d2
] != 7-d1
&& (NotDiagonalDir
[d2
] == NewAttnamIndex
|| !(RAND()&2))) {
241 v2 Pos
= TunnelEntry
+game::GetMoveVector(NotDiagonalDir
[d2
]);
242 AltitudeBuffer
[Pos
.X
][Pos
.Y
] = 1+RAND()%50;
243 TypeBuffer
[Pos
.X
][Pos
.Y
] = JungleType
;
244 GetWSquare(Pos
)->ChangeGWTerrain(jungle::Spawn());
248 for (int d2
= 0; d2
< 4; ++d2
) {
249 if (DiagonalDir
[d2
] != 7-d1
&&
250 (DiagonalDir
[d2
] == NewAttnamIndex
||
251 (Raised
[AdjacentDir
[d2
][0]] && Raised
[AdjacentDir
[d2
][1]] && !(RAND()&2)))) {
252 v2 Pos
= TunnelEntry
+game::GetMoveVector(DiagonalDir
[d2
]);
254 AltitudeBuffer
[Pos
.X
][Pos
.Y
] = 1+RAND()%50;
255 TypeBuffer
[Pos
.X
][Pos
.Y
] = JungleType
;
256 GetWSquare(Pos
)->ChangeGWTerrain(jungle::Spawn());
267 if (!Correct
) continue;
269 // tunnel entry, tunnel exit and New Attnam are ok, spawn
270 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
271 switch (PlaceDungeons
[f
]) {
273 GetWSquare(NewAttnamPos
)->ChangeOWTerrain(PlaceSpawners
[f
]());
274 SetEntryPos(NEW_ATTNAM
, NewAttnamPos
);
275 PlacePosition
[f
] = NewAttnamPos
;
277 case UNDER_WATER_TUNNEL
:
278 GetWSquare(TunnelEntry
)->ChangeOWTerrain(PlaceSpawners
[f
]());
279 SetEntryPos(UNDER_WATER_TUNNEL
, TunnelEntry
);
280 PlacePosition
[f
] = TunnelEntry
;
282 case UNDER_WATER_TUNNEL_EXIT
:
283 GetWSquare(TunnelExit
)->ChangeOWTerrain(PlaceSpawners
[f
]());
284 SetEntryPos(UNDER_WATER_TUNNEL_EXIT
, TunnelExit
);
285 PlacePosition
[f
] = TunnelExit
;
290 for (unsigned int f
= 0; f
< Places
.size(); ++f
) {
291 if (!Places
[f
]->IsAttnam() && !Places
[f
]->WantPetrusContinent()) continue;
292 if (!Places
[f
]->IsHidden()) GetWSquare(PlacePosition
[f
])->ChangeOWTerrain(PlaceSpawners
[f
]());
293 SetEntryPos(PlaceDungeons
[f
], PlacePosition
[f
]);
294 if (Places
[f
]->IsRevealed()) RevealEnvironment(PlacePosition
[f
], 1);
297 PLAYER
->PutTo(NewAttnamPos
);
299 CalculateLuminances();
300 CalculateNeighbourBitmapPoses();
303 delete [] OldAltitudeBuffer
;
304 delete [] OldTypeBuffer
;
308 void worldmap::RandomizeAltitude () {
309 game::BusyAnimation();
310 for (int x
= 0; x
< XSize
; ++x
)
311 for (int y
= 0; y
< YSize
; ++y
)
312 AltitudeBuffer
[x
][y
] = 4000 - RAND() % 8000;
316 void worldmap::SmoothAltitude () {
317 for (int c
= 0; c
< 10; ++c
) {
318 game::BusyAnimation();
320 for (y
= 0; y
< YSize
; ++y
) SafeSmooth(0, y
);
321 for (x
= 1; x
< XSize
- 1; ++x
) {
323 for (y
= 1; y
< YSize
- 1; ++y
) FastSmooth(x
, y
);
324 SafeSmooth(x
, YSize
- 1);
326 for (y
= 0; y
< YSize
; ++y
) SafeSmooth(XSize
- 1, y
);
331 void worldmap::FastSmooth (int x
, int y
) {
332 sLong HeightNear
= 0;
334 for (d
= 0; d
< 4; ++d
) HeightNear
+= OldAltitudeBuffer
[x
+ DirX
[d
]][y
+ DirY
[d
]];
335 for (d
= 4; d
< 8; ++d
) HeightNear
+= AltitudeBuffer
[x
+ DirX
[d
]][y
+ DirY
[d
]];
336 OldAltitudeBuffer
[x
][y
] = AltitudeBuffer
[x
][y
];
337 AltitudeBuffer
[x
][y
] = HeightNear
>> 3;
341 void worldmap::SafeSmooth (int x
, int y
) {
342 sLong HeightNear
= 0;
343 int d
, SquaresNear
= 0;
344 for (d
= 0; d
< 4; ++d
) {
347 if (IsValidPos(X
, Y
)) {
348 HeightNear
+= OldAltitudeBuffer
[X
][Y
];
352 for (d
= 4; d
< 8; ++d
) {
355 if (IsValidPos(X
, Y
)) {
356 HeightNear
+= AltitudeBuffer
[X
][Y
];
360 OldAltitudeBuffer
[x
][y
] = AltitudeBuffer
[x
][y
];
361 AltitudeBuffer
[x
][y
] = HeightNear
/ SquaresNear
;
365 void worldmap::GenerateClimate () {
366 game::BusyAnimation();
367 for (int y
= 0; y
< YSize
; ++y
) {
368 double DistanceFromEquator
= fabs(double(y
) / YSize
- 0.5);
369 truth LatitudeRainy
= DistanceFromEquator
<= 0.05 || (DistanceFromEquator
> 0.25 && DistanceFromEquator
<= 0.45);
370 for (int x
= 0; x
< XSize
; ++x
) {
371 if (AltitudeBuffer
[x
][y
] <= 0) {
372 TypeBuffer
[x
][y
] = OceanType
;
375 truth Rainy
= LatitudeRainy
;
377 for(int d
= 0; d
< 8; ++d
) {
378 v2 Pos
= v2(x
, y
) + game::GetMoveVector(d
);
379 if (IsValidPos(Pos
) && AltitudeBuffer
[Pos
.X
][Pos
.Y
] <= 0) {
385 int Temperature
= int(MAX_TEMPERATURE
-DistanceFromEquator
*LATITUDE_EFFECT
-AltitudeBuffer
[x
][y
]*ALTITUDE_EFFECT
);
387 if (Temperature
<= COLD
) Type
= Rainy
? SnowType
: GlacierType
;
388 else if (Temperature
<= MEDIUM
) Type
= Rainy
? EGForestType
: SnowType
;
389 else if (Temperature
<= WARM
) Type
= Rainy
? LForestType
: SteppeType
;
390 else if (Temperature
<= HOT
) Type
= Rainy
? LForestType
: DesertType
;
391 else Type
= Rainy
? JungleType
: DesertType
;
392 TypeBuffer
[x
][y
] = Type
;
398 void worldmap::SmoothClimate () {
399 for (int c
= 0; c
< 3; ++c
) {
400 game::BusyAnimation();
401 for (int x
= 0; x
< XSize
; ++x
)
402 for (int y
= 0; y
< YSize
; ++y
)
403 if ((OldTypeBuffer
[x
][y
] = TypeBuffer
[x
][y
]) != OceanType
)
404 TypeBuffer
[x
][y
] = WhatTerrainIsMostCommonAroundCurrentTerritorySquareIncludingTheSquareItself(x
, y
);
406 game::BusyAnimation();
407 for (int x
= 0; x
< XSize
; ++x
)
408 for (int y
= 0; y
< YSize
; ++y
)
409 Map
[x
][y
]->ChangeGWTerrain
410 (protocontainer
<gwterrain
>::GetProto(TypeBuffer
[x
][y
])->Spawn());
415 #define ANALYZE_TYPE(type) {\
417 for (c = 0; c < u; ++c) if (T == UsedType[c]) { ++TypeAmount[c]; break; }\
418 if (c == u) { UsedType[u] = T; TypeAmount[u++] = 1; }\
423 int worldmap::WhatTerrainIsMostCommonAroundCurrentTerritorySquareIncludingTheSquareItself (int x
, int y
) {
427 UsedType
[0] = TypeBuffer
[x
][y
];
429 for (d
= 0; d
< 4; ++d
) {
432 if (IsValidPos(X
, Y
)) ANALYZE_TYPE(OldTypeBuffer
[X
][Y
]);
434 for (d
= 4; d
< 8; ++d
) {
437 if (IsValidPos(X
, Y
)) ANALYZE_TYPE(TypeBuffer
[X
][Y
]);
440 for (c
= 1; c
< u
; ++c
) if (TypeAmount
[c
] > TypeAmount
[MostCommon
] && UsedType
[c
] != OceanType
) MostCommon
= c
;
441 return UsedType
[MostCommon
];
445 void worldmap::CalculateContinents () {
446 for (uInt c
= 1; c
< Continent
.size(); ++c
) delete Continent
[c
];
447 Continent
.resize(1, 0);
448 memset(ContinentBuffer
[0], 0, XSizeTimesYSize
*sizeof(uChar
));
449 game::BusyAnimation();
450 for (int x
= 0; x
< XSize
; ++x
) {
451 for (int y
= 0; y
< YSize
; ++y
) {
452 if (AltitudeBuffer
[x
][y
] > 0) {
453 truth Attached
= false;
454 for (int d
= 0; d
< 8; ++d
) {
455 v2 Pos
= v2(x
, y
)+game::GetMoveVector(d
);
456 if (IsValidPos(Pos
)) {
457 cint NearCont
= ContinentBuffer
[Pos
.X
][Pos
.Y
];
459 cint ThisCont
= ContinentBuffer
[x
][y
];
461 if (ThisCont
!= NearCont
) {
462 if (Continent
[ThisCont
]->GetSize() < Continent
[NearCont
]->GetSize())
463 Continent
[ThisCont
]->AttachTo(Continent
[NearCont
]);
465 Continent
[NearCont
]->AttachTo(Continent
[ThisCont
]);
467 } else Continent
[NearCont
]->Add(v2(x
, y
));
473 if (Continent
.size() == 255) {
474 RemoveEmptyContinents();
475 if (Continent
.size() == 255) ABORT("Valpurus shall not carry more continents!");
477 continent
*NewContinent
= new continent(Continent
.size());
478 NewContinent
->Add(v2(x
, y
));
479 Continent
.push_back(NewContinent
);
484 RemoveEmptyContinents();
485 for (uInt c
= 1; c
< Continent
.size(); ++c
) Continent
[c
]->GenerateInfo();
489 void worldmap::RemoveEmptyContinents () {
490 for (uInt c
= 1; c
< Continent
.size(); ++c
) {
491 if (!Continent
[c
]->GetSize()) {
492 for (uInt i
= Continent
.size() - 1; i
>= c
; i
--) {
493 if (Continent
[i
]->GetSize()) {
494 Continent
[i
]->AttachTo(Continent
[c
]);
496 Continent
.pop_back();
500 Continent
.pop_back();
508 void worldmap::Draw (truth
) const {
509 cint XMin
= Max(game::GetCamera().X
, 0);
510 cint YMin
= Max(game::GetCamera().Y
, 0);
511 cint XMax
= Min(XSize
, game::GetCamera().X
+game::GetScreenXSize());
512 cint YMax
= Min(YSize
, game::GetCamera().Y
+game::GetScreenYSize());
513 blitdata BlitData
= {
517 { TILE_SIZE
, TILE_SIZE
},
520 ALLOW_ANIMATE
|ALLOW_ALPHA
522 if (!game::GetSeeWholeMapCheatMode()) {
523 for (int x
= XMin
; x
< XMax
; ++x
) {
524 BlitData
.Dest
= game::CalculateScreenCoordinates(v2(x
, YMin
));
525 wsquare
**Square
= &Map
[x
][YMin
];
526 for (int y
= YMin
; y
< YMax
; ++y
, ++Square
, BlitData
.Dest
.Y
+= TILE_SIZE
) {
527 if ((*Square
)->LastSeen
) (*Square
)->Draw(BlitData
);
531 for (int x
= XMin
; x
< XMax
; ++x
) {
532 BlitData
.Dest
= game::CalculateScreenCoordinates(v2(x
, YMin
));
533 wsquare
**Square
= &Map
[x
][YMin
];
534 for (int y
= YMin
; y
< YMax
; ++y
, ++Square
, BlitData
.Dest
.Y
+= TILE_SIZE
) (*Square
)->Draw(BlitData
);
540 void worldmap::CalculateLuminances () {
541 for (feuLong c
= 0; c
< XSizeTimesYSize
; ++c
) Map
[0][c
]->CalculateLuminance();
545 void worldmap::CalculateNeighbourBitmapPoses () {
546 for (feuLong c
= 0; c
< XSizeTimesYSize
; ++c
) Map
[0][c
]->GetGWTerrain()->CalculateNeighbourBitmapPoses();
550 wsquare
*worldmap::GetNeighbourWSquare (v2 Pos
, int I
) const {
551 Pos
+= game::GetMoveVector(I
);
552 if (Pos
.X
>= 0 && Pos
.Y
>= 0 && Pos
.X
< XSize
&& Pos
.Y
< YSize
) return Map
[Pos
.X
][Pos
.Y
];
557 void worldmap::RevealEnvironment (v2 Pos
, int Radius
) {
559 femath::CalculateEnvironmentRectangle(Rect
, Border
, Pos
, Radius
);
560 for (int x
= Rect
.X1
; x
<= Rect
.X2
; ++x
)
561 for (int y
= Rect
.Y1
; y
<= Rect
.Y2
; ++y
)
562 Map
[x
][y
]->SignalSeen();
566 outputfile
&operator << (outputfile
&SaveFile
, const worldmap
*WorldMap
) {
567 WorldMap
->Save(SaveFile
);
572 inputfile
&operator >> (inputfile
&SaveFile
, worldmap
*&WorldMap
) {
573 WorldMap
= new worldmap
;
574 WorldMap
->Load(SaveFile
);
579 void worldmap::UpdateLOS () {
580 game::RemoveLOSUpdateRequest();
581 int Radius
= PLAYER
->GetLOSRange();
582 sLong RadiusSquare
= Radius
*Radius
;
583 v2 Pos
= PLAYER
->GetPos();
585 femath::CalculateEnvironmentRectangle(Rect
, Border
, Pos
, Radius
);
586 for (int x
= Rect
.X1
; x
<= Rect
.X2
; ++x
)
587 for (int y
= Rect
.Y1
; y
<= Rect
.Y2
; ++y
)
588 if (sLong(HypotSquare(Pos
.X
-x
, Pos
.Y
-y
)) <= RadiusSquare
) Map
[x
][y
]->SignalSeen();
592 void worldmap::RegisterPlace (owterrain
*plc
, cint ttype
, cint didx
, PlaceSpawner spawner
) {
593 Places
.push_back(plc
);
594 PlaceTypes
.push_back(ttype
);
595 PlaceDungeons
.push_back(didx
);
596 PlaceSpawners
.push_back(spawner
);