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
26 rawbitmap
* igraph::RawGraphic
[RAW_TYPES
];
27 bitmap
* igraph::Graphic
[GRAPHIC_TYPES
];
28 bitmap
* igraph::TileBuffer
;
29 bitmap
* igraph::FlagBuffer
;
30 cchar
* igraph::RawGraphicFileName
[] = { "graphics/GLTerra.pcx", "graphics/OLTerra.pcx", "graphics/Item.pcx", "graphics/Char.pcx", "graphics/Humanoid.pcx", "graphics/Effect.pcx", "graphics/Cursor.pcx" };
31 cchar
* igraph::GraphicFileName
[] = { "graphics/WTerra.pcx", "graphics/FOW.pcx", "graphics/Symbol.pcx", "graphics/Smiley.pcx" };
32 tilemap
igraph::TileMap
;
33 uChar
igraph::RollBuffer
[256];
34 int** igraph::BodyBitmapValidityMap
;
36 bitmap
* igraph::SilhouetteCache
[HUMANOID_BODYPARTS
][CONDITION_COLORS
][SILHOUETTE_TYPES
];
37 rawbitmap
* igraph::ColorizeBuffer
[2] = { new rawbitmap(TILE_V2
), new rawbitmap(TILE_V2
) };
38 bitmap
* igraph::Cursor
[CURSOR_TYPES
];
39 bitmap
* igraph::BigCursor
[CURSOR_TYPES
];
40 col16
igraph::CursorColor
[CURSOR_TYPES
] = { MakeRGB16(40, 40, 40),
42 MakeRGB16(100, 100, 255),
43 MakeRGB16(200, 200, 0) };
44 bitmap
* igraph::BackGround
;
45 int igraph::CurrentColorType
= -1;
49 static truth AlreadyInstalled
= false;
53 AlreadyInstalled
= true;
55 graphics::SetMode("IVAN " IVAN_VERSION
, festring(game::GetGameDir() + "graphics/Icon.bmp").CStr(), v2(800, 600), ivanconfig::GetFullScreenMode(), ivanconfig::GetDoubleResModifier());
56 DOUBLE_BUFFER
->ClearToColor(0);
57 graphics::BlitDBToScreen();
58 graphics::SetSwitchModeHandler(ivanconfig::SwitchModeHandler
);
59 graphics::LoadDefaultFont(game::GetGameDir() + "graphics/Font.pcx");
60 FONT
->CreateFontCache(WHITE
);
61 FONT
->CreateFontCache(LIGHT_GRAY
);
62 felist::CreateQuickDrawFontCaches(FONT
, WHITE
, 8);
63 felist::CreateQuickDrawFontCaches(FONT
, LIGHT_GRAY
, 8);
64 object::InitSparkleValidityArrays();
67 for(c
= 0; c
< RAW_TYPES
; ++c
)
68 RawGraphic
[c
] = new rawbitmap(game::GetGameDir() + RawGraphicFileName
[c
]);
70 for(c
= 0; c
< GRAPHIC_TYPES
; ++c
)
72 Graphic
[c
] = new bitmap(game::GetGameDir() + GraphicFileName
[c
]);
73 Graphic
[c
]->ActivateFastFlag();
76 ColorizeBuffer
[0]->CopyPaletteFrom(RawGraphic
[0]);
77 ColorizeBuffer
[1]->CopyPaletteFrom(RawGraphic
[0]);
78 TileBuffer
= new bitmap(TILE_V2
);
79 TileBuffer
->ActivateFastFlag();
80 TileBuffer
->InitPriorityMap(0);
81 FlagBuffer
= new bitmap(TILE_V2
);
82 FlagBuffer
->ActivateFastFlag();
83 FlagBuffer
->CreateAlphaMap(0);
84 Alloc2D(BodyBitmapValidityMap
, 8, 16);
85 CreateBodyBitmapValidityMaps();
86 CreateSilhouetteCaches();
88 for(c
= 0; c
< CURSOR_TYPES
; ++c
)
90 packcol16 Color
= CursorColor
[c
];
91 Cursor
[c
] = new bitmap(v2(48, 16), TRANSPARENT_COLOR
);
92 Cursor
[c
]->CreateAlphaMap(255);
93 GetCursorRawGraphic()->MaskedBlit(Cursor
[c
], ZERO_V2
, ZERO_V2
, v2(48, 16), &Color
);
94 BigCursor
[c
] = new bitmap(v2(96, 32), TRANSPARENT_COLOR
);
95 BigCursor
[c
]->CreateAlphaMap(255);
96 GetCursorRawGraphic()->MaskedBlit(BigCursor
[c
], v2(0, 16), ZERO_V2
, v2(96, 32), &Color
);
101 void igraph::DeInit()
105 for(c
= 0; c
< RAW_TYPES
; ++c
)
106 delete RawGraphic
[c
];
108 for(c
= 0; c
< GRAPHIC_TYPES
; ++c
)
113 delete [] BodyBitmapValidityMap
;
117 void igraph::DrawCursor(v2 Pos
, int CursorData
, int Index
)
119 /* Inefficient gum solution */
121 blitdata BlitData
= { DOUBLE_BUFFER
,
124 { TILE_SIZE
, TILE_SIZE
},
125 { ivanconfig::GetContrastLuminance() },
129 bitmap
* CursorBitmap
;
132 if(CursorData
& CURSOR_BIG
)
134 CursorBitmap
= BigCursor
[CursorData
&~CURSOR_FLAGS
];
135 BlitData
.Src
.X
= SrcX
= (Index
& 1) << 4;
136 BlitData
.Src
.Y
= (Index
& 2) << 3;
139 CursorBitmap
= Cursor
[CursorData
&~CURSOR_FLAGS
];
141 if(!(CursorData
& (CURSOR_FLASH
|CURSOR_TARGET
)))
143 CursorBitmap
->LuminanceMaskedBlit(BlitData
);
147 if(!(CursorData
& CURSOR_TARGET
))
149 int Tick
= GET_TICK() & 31;
150 CursorBitmap
->FillAlpha(95 + 10 * abs(Tick
- 16));
151 CursorBitmap
->AlphaLuminanceBlit(BlitData
);
155 int Tick
= (GET_TICK() << 2) / 3;
156 int Frame
= (Tick
>> 4) % 3;
157 int Base
= Frame
<< 4;
158 BlitData
.Src
.X
= SrcX
+ (CursorData
& CURSOR_BIG
? Base
<< 1 : Base
);
159 CursorBitmap
->FillAlpha(255 - (Tick
& 0xF) * 16);
160 CursorBitmap
->AlphaLuminanceBlit(BlitData
);
161 Base
= ((Frame
+ 1) % 3) << 4;
162 BlitData
.Src
.X
= SrcX
+ (CursorData
& CURSOR_BIG
? Base
<< 1 : Base
);
163 CursorBitmap
->FillAlpha((Tick
& 0xF) * 16);
164 CursorBitmap
->AlphaLuminanceBlit(BlitData
);
167 tilemap::iterator
igraph::AddUser(const graphicid
& GI
)
169 tilemap::iterator Iterator
= TileMap
.find(GI
);
171 if(Iterator
!= TileMap
.end())
173 tile
& Tile
= Iterator
->second
;
179 cint SpecialFlags
= GI
.SpecialFlags
;
180 cint BodyPartFlags
= SpecialFlags
& 0x78;
181 cint RotateFlags
= SpecialFlags
& 0x7;
182 cint Frame
= GI
.Frame
;
183 v2 SparklePos
= v2(GI
.SparklePosX
, GI
.SparklePosY
);
184 rawbitmap
* RawBitmap
= RawGraphic
[GI
.FileIndex
];
185 v2 RawPos
= v2(GI
.BitmapPosX
, GI
.BitmapPosY
);
187 if(BodyPartFlags
&& BodyPartFlags
< ST_OTHER_BODYPART
)
189 ColorizeBuffer
[0]->Clear();
190 EditBodyPartTile(RawBitmap
, ColorizeBuffer
[0], RawPos
, BodyPartFlags
);
191 RawBitmap
= ColorizeBuffer
[0];
192 RawPos
.X
= RawPos
.Y
= 0;
196 ColorizeBuffer
[1]->Clear();
197 SparklePos
= RotateTile(RawBitmap
, ColorizeBuffer
[1], RawPos
, SparklePos
, RotateFlags
);
198 RawBitmap
= ColorizeBuffer
[1];
203 ColorizeBuffer
[0]->Clear();
204 SparklePos
= RotateTile(RawBitmap
, ColorizeBuffer
[0], RawPos
, SparklePos
, RotateFlags
);
205 RawBitmap
= ColorizeBuffer
[0];
206 RawPos
.X
= RawPos
.Y
= 0;
209 bitmap
* Bitmap
= RawBitmap
->Colorize(RawPos
, TILE_V2
, GI
.Position
, GI
.Color
, GI
.BaseAlpha
, GI
.Alpha
, GI
.RustData
, !(GI
.SpecialFlags
& ST_DISALLOW_R_COLORS
));
210 Bitmap
->ActivateFastFlag();
213 Bitmap
->InitPriorityMap(SpecialFlags
& ST_CLOAK
? CLOAK_PRIORITY
: AVERAGE_PRIORITY
);
215 if(GI
.OutlineColor
!= TRANSPARENT_COLOR
)
216 Bitmap
->Outline(GI
.OutlineColor
, GI
.OutlineAlpha
, BodyPartFlags
!= ST_WIELDED
? ARMOR_OUTLINE_PRIORITY
: AVERAGE_PRIORITY
);
218 if(SparklePos
.X
!= SPARKLE_POS_X_ERROR
)
219 Bitmap
->CreateSparkle(SparklePos
+ GI
.Position
, GI
.SparkleFrame
);
222 Bitmap
->CreateFlies(GI
.Seed
, Frame
, GI
.FlyAmount
);
224 cint WobbleData
= GI
.WobbleData
;
226 if(WobbleData
& WOBBLE
)
228 int Speed
= (WobbleData
& WOBBLE_SPEED_RANGE
) >> WOBBLE_SPEED_SHIFT
;
229 int Freq
= (WobbleData
& WOBBLE_FREQ_RANGE
) >> WOBBLE_FREQ_SHIFT
;
230 int WobbleMask
= 7 >> Freq
<< (6 - Speed
);
232 if(!(Frame
& WobbleMask
))
233 Bitmap
->Wobble(Frame
& ((1 << (6 - Speed
)) - 1), Speed
, WobbleData
& WOBBLE_HORIZONTALLY_BIT
);
236 if(SpecialFlags
& ST_FLAMES
)
238 feuLong SeedNFlags
= (SpecialFlags
>> ST_FLAME_SHIFT
& 3) | (GI
.Seed
<< 4);
239 Bitmap
->CreateFlames(RawBitmap
, RawPos
- GI
.Position
, SeedNFlags
, Frame
);
242 if(SpecialFlags
& ST_LIGHTNING
&& !((Frame
+ 1) & 7))
243 Bitmap
->CreateLightning(GI
.Seed
+ Frame
, WHITE
);
245 return TileMap
.insert(std::make_pair(GI
, tile(Bitmap
))).first
;
249 void igraph::EditBodyPartTile(rawbitmap
* Source
, rawbitmap
* Dest
, v2 Pos
, int BodyPartFlags
)
251 if(BodyPartFlags
== ST_RIGHT_ARM
)
252 Source
->NormalBlit(Dest
, Pos
, ZERO_V2
, v2(8, 16));
253 else if(BodyPartFlags
== ST_LEFT_ARM
)
254 Source
->NormalBlit(Dest
, v2(Pos
.X
+ 8, Pos
.Y
), v2(8, 0), v2(8, 16));
255 else if(BodyPartFlags
== ST_GROIN
)
257 Source
->NormalBlit(Dest
, v2(Pos
.X
, Pos
.Y
+ 8), v2(0, 8), v2(16, 2));
261 for(V
.Y
= 10/*, i = 0*/; V
.Y
< 13; ++V
.Y
)
262 for(V
.X
= V
.Y
- 5; V
.X
< 20 - V
.Y
; ++V
.X
)
263 Dest
->PutPixel(V
, Source
->GetPixel(Pos
+ V
));
265 else if(BodyPartFlags
== ST_RIGHT_LEG
)
267 /* Right leg from the character's, NOT the player's point of view */
269 Source
->NormalBlit(Dest
, v2(Pos
.X
, Pos
.Y
+ 10), v2(0, 10), v2(8, 6));
270 Dest
->PutPixel(v2(5, 10), TRANSPARENT_PALETTE_INDEX
);
271 Dest
->PutPixel(v2(6, 10), TRANSPARENT_PALETTE_INDEX
);
272 Dest
->PutPixel(v2(7, 10), TRANSPARENT_PALETTE_INDEX
);
273 Dest
->PutPixel(v2(6, 11), TRANSPARENT_PALETTE_INDEX
);
274 Dest
->PutPixel(v2(7, 11), TRANSPARENT_PALETTE_INDEX
);
275 Dest
->PutPixel(v2(7, 12), TRANSPARENT_PALETTE_INDEX
);
277 else if(BodyPartFlags
== ST_LEFT_LEG
)
279 /* Left leg from the character's, NOT the player's point of view */
281 Source
->NormalBlit(Dest
, v2(Pos
.X
+ 8, Pos
.Y
+ 10), v2(8, 10), v2(8, 6));
282 Dest
->PutPixel(v2(8, 10), TRANSPARENT_PALETTE_INDEX
);
283 Dest
->PutPixel(v2(9, 10), TRANSPARENT_PALETTE_INDEX
);
284 Dest
->PutPixel(v2(8, 11), TRANSPARENT_PALETTE_INDEX
);
288 v2
igraph::RotateTile(rawbitmap
* Source
, rawbitmap
* Dest
, v2 Pos
, v2 SparklePos
, int RotateFlags
)
290 Source
->NormalBlit(Dest
, Pos
, ZERO_V2
, TILE_V2
, RotateFlags
);
292 if(SparklePos
.X
!= SPARKLE_POS_X_ERROR
)
294 if(RotateFlags
& ROTATE
)
296 cint T
= SparklePos
.X
;
297 SparklePos
.X
= 15 - SparklePos
.Y
;
301 if(RotateFlags
& MIRROR
)
302 SparklePos
.X
= 15 - SparklePos
.X
;
304 if(RotateFlags
& FLIP
)
305 SparklePos
.Y
= 15 - SparklePos
.Y
;
311 void igraph::RemoveUser(tilemap::iterator Iterator
)
313 /*k8!!! memory leak by me!*/
314 /*tile& Tile = Iterator->second;
319 TileMap.erase(Iterator);
323 outputfile
& operator<<(outputfile
& SaveFile
, const graphicid
& Value
)
325 SaveFile
.Write(reinterpret_cast<cchar
*>(&Value
), sizeof(Value
));
329 inputfile
& operator>>(inputfile
& SaveFile
, graphicid
& Value
)
331 SaveFile
.Read(reinterpret_cast<char*>(&Value
), sizeof(Value
));
335 graphicdata::~graphicdata()
339 for(int c
= 0; c
< AnimationFrames
; ++c
)
340 igraph::RemoveUser(GraphicIterator
[c
]);
343 delete [] GraphicIterator
;
347 void graphicdata::Save(outputfile
& SaveFile
) const
349 SaveFile
<< (int)AnimationFrames
;
351 for(int c
= 0; c
< AnimationFrames
; ++c
)
352 SaveFile
<< GraphicIterator
[c
]->first
;
355 void graphicdata::Load(inputfile
& SaveFile
)
357 SaveFile
>> (int&)AnimationFrames
;
361 Picture
= new bitmap
*[AnimationFrames
];
362 GraphicIterator
= new tilemap::iterator
[AnimationFrames
];
365 for(int c
= 0; c
< AnimationFrames
; ++c
)
367 SaveFile
>> GraphicID
;
368 Picture
[c
] = (GraphicIterator
[c
] = igraph::AddUser(GraphicID
))->second
.Bitmap
;
373 outputfile
& operator<<(outputfile
& SaveFile
, const graphicdata
& Data
)
379 inputfile
& operator>>(inputfile
& SaveFile
, graphicdata
& Data
)
385 void graphicdata::Retire()
389 for(int c
= 0; c
< AnimationFrames
; ++c
)
390 igraph::RemoveUser(GraphicIterator
[c
]);
394 delete [] GraphicIterator
;
398 cint
* igraph::GetBodyBitmapValidityMap(int SpecialFlags
)
400 return BodyBitmapValidityMap
[(SpecialFlags
& 0x38) >> 3];
403 void igraph::CreateBodyBitmapValidityMaps()
405 memset(BodyBitmapValidityMap
[0], 0xFF, 128 * sizeof(int));
406 int* Map
= BodyBitmapValidityMap
[ST_RIGHT_ARM
>> 3];
409 for(x
= 8; x
< 16; ++x
)
412 Map
= BodyBitmapValidityMap
[ST_LEFT_ARM
>> 3];
414 for(x
= 0; x
< 8; ++x
)
417 Map
= BodyBitmapValidityMap
[ST_GROIN
>> 3];
418 memset(Map
, 0, 16 * sizeof(int));
420 for(y
= 10; y
< 13; ++y
)
421 for(x
= y
- 5; x
< 20 - y
; ++x
)
424 Map
= BodyBitmapValidityMap
[ST_RIGHT_LEG
>> 3];
426 for(x
= 8; x
< 16; ++x
)
429 Map
[5] &= ~(1 << 10);
430 Map
[6] &= ~(1 << 10);
431 Map
[7] &= ~(1 << 10);
432 Map
[6] &= ~(1 << 11);
433 Map
[7] &= ~(1 << 11);
434 Map
[7] &= ~(1 << 12);
436 Map
= BodyBitmapValidityMap
[ST_LEFT_LEG
>> 3];
438 for(x
= 0; x
< 8; ++x
)
441 Map
[8] &= ~(1 << 10);
442 Map
[9] &= ~(1 << 10);
443 Map
[8] &= ~(1 << 11);
446 void igraph::LoadMenu()
448 Menu
= new bitmap(game::GetGameDir() + "graphics/Menu.pcx");
451 void igraph::UnLoadMenu()
456 void igraph::CreateSilhouetteCaches()
458 int BodyPartSilhouetteMColorIndex
[HUMANOID_BODYPARTS
] = { 3, 0, 1, 2, 1, 2, 3 };
459 col24 ConditionColor
[CONDITION_COLORS
] = { MakeRGB16(48, 48, 48),
460 MakeRGB16(120, 0, 0),
461 MakeRGB16(180, 0, 0),
462 MakeRGB16(180, 120, 120),
463 MakeRGB16(180, 180, 180) };
466 for(int c1
= 0; c1
< HUMANOID_BODYPARTS
; ++c1
)
471 for(int c2
= 0; c2
< CONDITION_COLORS
; ++c2
)
473 packcol16 Color
[4] = { 0, 0, 0, 0 };
474 Color
[BodyPartSilhouetteMColorIndex
[c1
]] = ConditionColor
[c2
];
476 for(int c3
= 0; c3
< SILHOUETTE_TYPES
; ++c3
)
478 SilhouetteCache
[c1
][c2
][c3
] = new bitmap(SILHOUETTE_SIZE
, 0);
479 RawGraphic
[GR_CHARACTER
]->MaskedBlit(SilhouetteCache
[c1
][c2
][c3
],
481 SILHOUETTE_SIZE
, Color
);
484 SilhouetteCache
[c1
][c2
][SILHOUETTE_INTER_LACED
]->InterLace();
489 void igraph::CreateBackGround(int ColorType
)
491 if(CurrentColorType
== ColorType
)
494 CurrentColorType
= ColorType
;
496 BackGround
= new bitmap(RES
);
499 Alloc2D(Map
, Side
, Side
);
500 femath::GenerateFractalMap(Map
, Side
, Side
- 1, 800);
502 for(int x
= 0; x
< RES
.X
; ++x
)
503 for(int y
= 0; y
< RES
.Y
; ++y
)
505 int E
= Limit
<int>(abs(Map
[1024 - x
][1024 - (RES
.Y
- y
)]) / 30, 0, 100);
506 BackGround
->PutPixel(x
, y
, GetBackGroundColor(E
));
512 col16
igraph::GetBackGroundColor(int Element
)
514 switch(CurrentColorType
)
516 case GRAY_FRACTAL
: return MakeRGB16(Element
, Element
, Element
);
517 case RED_FRACTAL
: return MakeRGB16(Element
+ (Element
>> 1), Element
/ 3, Element
/ 3);
518 case GREEN_FRACTAL
: return MakeRGB16(Element
/ 3, Element
+ (Element
>> 2), Element
/ 3);
519 case BLUE_FRACTAL
: return MakeRGB16(Element
/ 3, Element
/ 3, Element
+ (Element
>> 1));
520 case YELLOW_FRACTAL
: return MakeRGB16(Element
+ (Element
>> 1), Element
+ (Element
>> 1), Element
/ 3);
526 void igraph::BlitBackGround(v2 Pos
, v2 Border
)
528 blitdata B
= { DOUBLE_BUFFER
,
531 { Border
.X
, Border
.Y
},
536 BackGround
->NormalBlit(B
);
539 bitmap
* igraph::GenerateScarBitmap(int BodyPart
, int Severity
, int Color
)
541 bitmap
* CacheBitmap
= SilhouetteCache
[BodyPart
][0][SILHOUETTE_NORMAL
];
542 bitmap
* Scar
= new bitmap(SILHOUETTE_SIZE
, 0);
547 StartPos
= v2(RAND_N(SILHOUETTE_SIZE
.X
),RAND_N(SILHOUETTE_SIZE
.Y
));
548 if(CacheBitmap
->GetPixel(StartPos
) != 0)
555 double Angle
= 2 * FPI
* RAND_256
/ 256;
556 EndPos
.X
= int(StartPos
.X
+ cos(Angle
) * (Severity
+ 1));
557 EndPos
.Y
= int(StartPos
.Y
+ sin(Angle
) * (Severity
+ 1));
558 if(CacheBitmap
->IsValidPos(EndPos
) && CacheBitmap
->GetPixel(EndPos
) != 0)
561 Scar
->DrawLine(StartPos
, EndPos
, Color
);