1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #include "../../drawing/Drawing.h"
11 #include "../../interface/Viewport.h"
12 #include "../../localisation/StringIds.h"
13 #include "../../world/Balloon.h"
14 #include "../../world/Duck.h"
15 #include "../../world/Fountain.h"
16 #include "../../world/MoneyEffect.h"
17 #include "../../world/Particle.h"
18 #include "../Paint.h"
19 #include "Paint.Sprite.h"
20 
21 /** rct2: 0x0097EDA4 */
22 static constexpr const int8_t money_wave[] = {
23     0, 1, 2, 2, 3, 3, 3, 3, 2, 2, 1, 0, -1, -2, -2, -3, -3, -3, -3, -2, -2, -1,
24     0, 1, 2, 2, 3, 3, 3, 3, 2, 2, 1, 0, -1, -2, -2, -3, -3, -3, -3, -2, -2, -1,
25 };
26 
27 /** rct2: 0x0097ED90 */
28 const uint32_t vehicle_particle_base_sprites[] = {
29     22577, 22589, 22601, 22613, 22625,
30 };
31 
PaintEntity(paint_session * session,const SteamParticle * particle,int32_t imageDirection)32 template<> void PaintEntity(paint_session* session, const SteamParticle* particle, int32_t imageDirection)
33 {
34     uint32_t imageId = 22637 + (particle->frame / 256);
35     PaintAddImageAsParent(session, imageId, { 0, 0, particle->z }, { 1, 1, 0 });
36 }
37 
PaintEntity(paint_session * session,const MoneyEffect * moneyEffect,int32_t imageDirection)38 template<> void PaintEntity(paint_session* session, const MoneyEffect* moneyEffect, int32_t imageDirection)
39 {
40     rct_drawpixelinfo* dpi = &session->DPI;
41 
42     if (dpi->zoom_level > 0)
43     {
44         return;
45     }
46     if (moneyEffect == nullptr)
47         return;
48     auto [stringId, value] = moneyEffect->GetStringId();
49     PaintFloatingMoneyEffect(
50         session, value, stringId, moneyEffect->y, moneyEffect->z, const_cast<int8_t*>(&money_wave[moneyEffect->Wiggle % 22]),
51         moneyEffect->OffsetX, session->CurrentRotation);
52 }
53 
PaintEntity(paint_session * session,const VehicleCrashParticle * particle,int32_t imageDirection)54 template<> void PaintEntity(paint_session* session, const VehicleCrashParticle* particle, int32_t imageDirection)
55 {
56     rct_drawpixelinfo* dpi = &session->DPI;
57     if (dpi->zoom_level > 0)
58     {
59         return;
60     }
61 
62     if (particle == nullptr)
63         return;
64     uint32_t imageId = vehicle_particle_base_sprites[particle->crashed_sprite_base] + particle->frame / 256;
65     imageId = imageId | (particle->colour[0] << 19) | (particle->colour[1] << 24) | IMAGE_TYPE_REMAP | IMAGE_TYPE_REMAP_2_PLUS;
66     PaintAddImageAsParent(session, imageId, { 0, 0, particle->z }, { 1, 1, 0 });
67 }
68 
PaintEntity(paint_session * session,const ExplosionCloud * particle,int32_t imageDirection)69 template<> void PaintEntity(paint_session* session, const ExplosionCloud* particle, int32_t imageDirection)
70 {
71     if (particle == nullptr)
72         return;
73     uint32_t imageId = 22878 + (particle->frame / 256);
74     PaintAddImageAsParent(session, imageId, { 0, 0, particle->z }, { 1, 1, 0 });
75 }
76 
PaintEntity(paint_session * session,const CrashSplashParticle * crashSplash,int32_t imageDirection)77 template<> void PaintEntity(paint_session* session, const CrashSplashParticle* crashSplash, int32_t imageDirection)
78 {
79     if (crashSplash == nullptr)
80         return;
81     uint32_t imageId = 22927 + (crashSplash->frame / 256);
82     PaintAddImageAsParent(session, imageId, { 0, 0, crashSplash->z }, { 1, 1, 0 });
83 }
84 
PaintEntity(paint_session * session,const ExplosionFlare * flare,int32_t imageDirection)85 template<> void PaintEntity(paint_session* session, const ExplosionFlare* flare, int32_t imageDirection)
86 {
87     // Like a flare
88     if (flare == nullptr)
89         return;
90     uint32_t imageId = 22896 + (flare->frame / 256);
91     PaintAddImageAsParent(session, imageId, { 0, 0, flare->z }, { 1, 1, 0 });
92 }
93 
94 constexpr uint32_t JumpingFountainSnowBaseImage = 23037;
95 constexpr uint32_t JumpingFountainWaterBaseImage = 22973;
96 
PaintEntity(paint_session * session,const JumpingFountain * jumpingFountain,int32_t imageDirection)97 template<> void PaintEntity(paint_session* session, const JumpingFountain* jumpingFountain, int32_t imageDirection)
98 {
99     rct_drawpixelinfo* dpi = &session->DPI;
100     if (dpi->zoom_level > 0)
101     {
102         return;
103     }
104 
105     if (jumpingFountain == nullptr)
106         return;
107     uint16_t height = jumpingFountain->z + 6;
108     int32_t ebx = imageDirection / 8;
109 
110     // Fountain is firing anti clockwise
111     bool reversed = (jumpingFountain->FountainFlags & FOUNTAIN_FLAG::DIRECTION);
112     // Fountain rotation
113     bool rotated = (jumpingFountain->sprite_direction / 16) & 1;
114     bool isAntiClockwise = (ebx / 2) & 1; // Clockwise or Anti-clockwise
115 
116     // These cancel each other out
117     if (reversed != rotated)
118     {
119         isAntiClockwise = !isAntiClockwise;
120     }
121 
122     uint32_t baseImageId = (jumpingFountain->FountainType == JumpingFountainType::Snow) ? JumpingFountainSnowBaseImage
123                                                                                         : JumpingFountainWaterBaseImage;
124     uint32_t imageId = baseImageId + ebx * 16 + jumpingFountain->frame;
125     constexpr std::array antiClockWiseBoundingBoxes = {
126         CoordsXY{ -COORDS_XY_STEP, -3 },
127         CoordsXY{ 0, -3 },
128     };
129     constexpr std::array clockWiseBoundingBoxes = {
130         CoordsXY{ -COORDS_XY_STEP, 3 },
131         CoordsXY{ 0, 3 },
132     };
133 
134     auto bb = isAntiClockwise ? antiClockWiseBoundingBoxes : clockWiseBoundingBoxes;
135 
136     PaintAddImageAsParentRotated(session, ebx, imageId, 0, 0, 32, 1, 3, height, bb[ebx & 1].x, bb[ebx & 1].y, height);
137 }
138 
PaintEntity(paint_session * session,const Balloon * balloon,int32_t imageDirection)139 template<> void PaintEntity(paint_session* session, const Balloon* balloon, int32_t imageDirection)
140 {
141     if (balloon == nullptr)
142         return;
143     uint32_t imageId = 22651 + (balloon->frame & 7);
144     if (balloon->popped != 0)
145     {
146         imageId += 8;
147     }
148 
149     imageId = imageId | (balloon->colour << 19) | IMAGE_TYPE_REMAP;
150     PaintAddImageAsParent(session, imageId, { 0, 0, balloon->z }, { 1, 1, 0 });
151 }
152 
PaintEntity(paint_session * session,const Duck * duck,int32_t imageDirection)153 template<> void PaintEntity(paint_session* session, const Duck* duck, int32_t imageDirection)
154 {
155     rct_drawpixelinfo* dpi = &session->DPI;
156     if (dpi->zoom_level <= 1)
157     {
158         if (duck == nullptr)
159             return;
160         uint32_t imageId = duck->GetFrameImage(imageDirection);
161         if (imageId != 0)
162         {
163             PaintAddImageAsParent(session, imageId, { 0, 0, duck->z }, { 1, 1, 0 });
164         }
165     }
166 }
167