diff --git a/engines/ags/module.mk b/engines/ags/module.mk index 65f6f9dcd1a..6f057102c31 100644 --- a/engines/ags/module.mk +++ b/engines/ags/module.mk @@ -351,7 +351,8 @@ MODULE_OBJS = \ plugins/ags_shell/ags_shell.o \ plugins/ags_tcp_ip/ags_tcp_ip.o \ plugins/ags_wadjet_util/ags_wadjet_util.o \ - plugins/ags_waves/ags_waves.o + plugins/ags_waves/ags_waves.o \ + plugins/ags_waves/draw.o ifdef ENABLE_AGS_TESTS MODULE_OBJS += \ diff --git a/engines/ags/plugins/ags_waves/ags_waves.cpp b/engines/ags/plugins/ags_waves/ags_waves.cpp index 75f97887575..ccec1fef41b 100644 --- a/engines/ags/plugins/ags_waves/ags_waves.cpp +++ b/engines/ags/plugins/ags_waves/ags_waves.cpp @@ -26,6 +26,11 @@ namespace AGS3 { namespace Plugins { namespace AGSWaves { +const unsigned int Magic = 0xACAB0000; +const unsigned int Version = 1; +const unsigned int SaveMagic = Magic + Version; +const float PI = 3.14159265f; + const char *AGSWaves::AGS_GetPluginName() { return "AGS Waves"; } @@ -33,6 +38,15 @@ const char *AGSWaves::AGS_GetPluginName() { void AGSWaves::AGS_EngineStartup(IAGSEngine *engine) { PluginBase::AGS_EngineStartup(engine); + if (engine->version < 13) + engine->AbortGame("Engine interface is too old, need newer version of AGS."); + + StartingValues(); + + Character_GetX = (SCAPI_CHARACTER_GETX)engine->GetScriptFunctionAddress("Character::get_X"); + Character_GetY = (SCAPI_CHARACTER_GETY)engine->GetScriptFunctionAddress("Character::get_Y"); + Character_ID = (SCAPI_CHARACTER_ID)engine->GetScriptFunctionAddress("Character::ID"); + SCRIPT_METHOD(DrawScreenEffect, AGSWaves::DrawScreenEffect); SCRIPT_METHOD(SFX_Play, AGSWaves::SFX_Play); SCRIPT_METHOD(SFX_SetVolume, AGSWaves::SFX_SetVolume); @@ -86,7 +100,8 @@ void AGSWaves::AGS_EngineStartup(IAGSEngine *engine) { } void AGSWaves::DrawScreenEffect(ScriptMethodParams ¶ms) { - //PARAMS4(int, sprite, int, sprite_prev, int, ide, int, n); + PARAMS4(int, sprite, int, sprite_prev, int, ide, int, n); + DrawEffect(sprite, sprite_prev, ide, n); } void AGSWaves::SFX_Play(ScriptMethodParams ¶ms) { @@ -195,16 +210,62 @@ void AGSWaves::ReadVariable(ScriptMethodParams ¶ms) { } void AGSWaves::GameDoOnceOnly(ScriptMethodParams ¶ms) { - //PARAMS1(const char *, value); +// PARAMS1(const char *, value); + + GetGDState(params); + if (params._result) { + // Set state to false + params.push_back(false); + SetGDState(params); + + params._result = true; + } else { + params._result = false; + } } void AGSWaves::SetGDState(ScriptMethodParams ¶ms) { - //PARAMS2(const char *, value, bool, setvalue); + PARAMS2(const char *, value, bool, setValue); + + int id = -1; + for (int i = 0; i <= usedTokens; i++) { + if (Token[i] != NULL && strcmp(Token[i], value) == 0) { + id = i; + TokenUnUsed[i] = setValue; + i = usedTokens + 1; + } + } + + if (id == -1) { + // It doesn't find it while trying to set its state + // create the thing with said state + id = usedTokens; + TokenUnUsed[id] = setValue; + if (Token[id] != NULL) + free(Token[id]); + + Token[id] = scumm_strdup(value); + usedTokens++; + } } void AGSWaves::GetGDState(ScriptMethodParams ¶ms) { - //PARAMS1(const char *, value); - params._result = false; + PARAMS1(const char *, value); + + int id = -1; + + for (int i = 0; i <= usedTokens; i++) { + if (Token[i] != NULL && strcmp(Token[i], value) == 0) { + id = i; + i = usedTokens + 1; + } + } + + if (id == -1) { + params._result = true; + } else { + params._result = TokenUnUsed[id]; + } } void AGSWaves::ResetAllGD(ScriptMethodParams ¶ms) { @@ -287,6 +348,32 @@ void AGSWaves::SetWalkbehindBaserine(ScriptMethodParams ¶ms) { //PARAMS2(int, id, int, base); } +void AGSWaves::StartingValues() { + GeneralAudio.NumOfChannels = 0; + GeneralAudio.Initialized = false; + GeneralAudio.Disabled = false; + GeneralAudio.FilterFrequency = 10; + GeneralAudio.SoundValue = 0; + MFXStream.ID = 0; + MFXStream.Channel = -1; + MFXStream.Switch = false; + MFXStream.FadeTime = 0; + MFXStream.FadeRate = 0.0; + MFXStream.FadeVolume = 0.0; + MFXStream.HaltedZero = false; + MFXStream.HaltedOne = false; + + int j = 0; + while (j < 2) { + globalStream[j].Filename = NULL; + globalStream[j].repeat = 0; + globalStream[j].volume = 0; + globalStream[j].Vorbis = NULL; + globalStream[j].fix_click = false; + j++; + } +} + } // namespace AGSWaves } // namespace Plugins } // namespace AGS3 diff --git a/engines/ags/plugins/ags_waves/ags_waves.h b/engines/ags/plugins/ags_waves/ags_waves.h index 9a0170838e9..5b4e6461721 100644 --- a/engines/ags/plugins/ags_waves/ags_waves.h +++ b/engines/ags/plugins/ags_waves/ags_waves.h @@ -24,12 +24,13 @@ #define AGS_PLUGINS_AGS_WAVES_AGS_WAVES_H #include "ags/plugins/ags_plugin.h" +#include "ags/plugins/ags_waves/vars.h" namespace AGS3 { namespace Plugins { namespace AGSWaves { -class AGSWaves : public PluginBase { +class AGSWaves : public PluginBase, public Vars { SCRIPT_HASH(AGSWaves) private: void DrawScreenEffect(ScriptMethodParams ¶ms); @@ -82,8 +83,15 @@ private: void TintProper(ScriptMethodParams ¶ms); void GetWalkbehindBaserine(ScriptMethodParams ¶ms); void SetWalkbehindBaserine(ScriptMethodParams ¶ms); + +private: + void StartingValues(); + + void CastWave(int delayMax, int PixelsWide, int n); + void DrawEffect(int sprite_a, int sprite_b, int id, int n); + public: - AGSWaves() : PluginBase() {} + AGSWaves() : PluginBase(), Vars() {} virtual ~AGSWaves() {} const char *AGS_GetPluginName() override; diff --git a/engines/ags/plugins/ags_waves/draw.cpp b/engines/ags/plugins/ags_waves/draw.cpp new file mode 100644 index 00000000000..0ecbb92f757 --- /dev/null +++ b/engines/ags/plugins/ags_waves/draw.cpp @@ -0,0 +1,139 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or(at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "ags/plugins/ags_waves/ags_waves.h" +#include "ags/ags.h" + +namespace AGS3 { +namespace Plugins { +namespace AGSWaves { + +void AGSWaves::CastWave(int delayMax, int PixelsWide, int n) { + tDy[n]++; + if (tDy[n] > delayMax) { + tDy[n] = 0; + if (direction[n] == 0) dY[n]++; + if (direction[n] == 1) dY[n]--; + if ((dY[n] > PixelsWide &&direction[n] == 0) || (dY[n] < (-PixelsWide) && direction[n] == 1)) { + if (direction[n] == 0) { + dY[n] = PixelsWide; direction[n] = 1; + } else { + dY[n] = -PixelsWide; direction[n] = 0; + } + } + } +} + +void AGSWaves::DrawEffect(int sprite_a, int sprite_b, int id, int n) { + int x, y; + + BITMAP *src_a = _engine->GetSpriteGraphic(sprite_a); + BITMAP *src_b = _engine->GetSpriteGraphic(sprite_b); + + unsigned int **pixel_a = (unsigned int **)_engine->GetRawBitmapSurface(src_a); + unsigned int **pixel_b = (unsigned int **)_engine->GetRawBitmapSurface(src_b); + + int src_width = 640; + int src_height = 360; + int src_depth = 32; + _engine->GetBitmapDimensions(src_a, &src_width, &src_height, &src_depth); + + + + for (y = 0; y < src_height; y++) { + if (id == 1) + CastWave(15, 1, n); + if (id == 0 || id == 9 || id == 2 || id == 3 || id == 6 || id == 8) + CastWave(2, 1, n); + if (id == 4) + CastWave(15, 4, n); + if (id == 5 || id == 7 || id == 10) { + //x=0; + CastWave(3, 1, n); + } + if (id == 11) { + //x=0; + CastWave(3, 2, n); + } + if (id == 16) CastWave(4, 1, n); + if (id == 17) CastWave(6, 1, n); + + + for (x = 0; x < src_width; x++) { + unsigned int colorfromB = pixel_b[y][x]; + int getX = x; + int getY = y; + + if (id == 0) { + getX = x - ::AGS::g_vm->getRandomNumber(1) - 2; + getY = y + dY[n]; + } + if (id == 1 || id == 4) { + getX = x; + getY = y + dY[n]; + } + if (id == 2) { + getX = x + dY[n]; + getY = y - ::AGS::g_vm->getRandomNumber(1) - 2; + } + if (id == 3) { + getX = x; + getY = y - ::AGS::g_vm->getRandomNumber(1) - 2; + } + if (id == 5) { + getX = x + dY[n]; + getY = y - ::AGS::g_vm->getRandomNumber(1) - 2; + } + if (id == 6 || id == 16) { + getX = x + dY[n]; + getY = y - (0 /* rand() % 1 */) - 1; + } + if (id == 7 || id == 17) { + getX = x + dY[n]; + getY = y - (0 /* rand() % 1 */) - 1; + } + if (id == 8) { + getX = x + dY[n]; + getY = y + ::AGS::g_vm->getRandomNumber(1) - 2; + } + if (id == 10 || id == 9 || id == 11) { + getX = x + dY[n]; + getY = y; + } + + if (getX < 0) getX = 0; + if (getX > src_width - 1) getX = src_width - 1; + if (getY > src_height - 1) getY = src_height - 1; + if (getY < 0) getY = 0; + + + pixel_a[getY][getX] = colorfromB; // + } + } + + _engine->ReleaseBitmapSurface(src_a); + _engine->ReleaseBitmapSurface(src_b); +} + +} // namespace AGSWaves +} // namespace Plugins +} // namespace AGS3 diff --git a/engines/ags/plugins/ags_waves/vars.h b/engines/ags/plugins/ags_waves/vars.h new file mode 100644 index 00000000000..458b95774a8 --- /dev/null +++ b/engines/ags/plugins/ags_waves/vars.h @@ -0,0 +1,224 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or(at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef AGS_PLUGINS_AGS_WAVES_VARS_H +#define AGS_PLUGINS_AGS_WAVES_VARS_H + +namespace AGS3 { +namespace Plugins { +namespace AGSWaves { + +#define texWidth 240 +#define texHeight 240 +#define screenWidth 640 +#define screenHeight 360 + +// TODO: Dummy definitions that need to be fixed +typedef void *stb_vorbis; +typedef void *Mix_Chunk; +typedef int SDL_AudioSpec; +typedef int SDL_AudioDeviceID; + +struct Particle { + int x, y; +}; + +/*---------------------------------------------*/ + +typedef int (*SCAPI_CHARACTER_GETX)(AGSCharacter *ch); +typedef int (*SCAPI_CHARACTER_GETY)(AGSCharacter *ch); +typedef int (*SCAPI_CHARACTER_ID) (AGSCharacter *ch); + +struct getMus { + char musicPath[1024]; +}; + +//WAVE SOUNDS FILES +struct Soundeffect { + Mix_Chunk *chunk; + int repeat; + int volume; + int playing; + int allow; + int channel; + int filter; +}; + +struct Aud { + int NumOfChannels; + bool Initialized; + bool Disabled; + int FilterFrequency; + int SoundValue; +}; + +struct Mus { + int ID; + int FadeTime; + float FadeRate; + float FadeVolume; + int Channel; + bool Switch; + bool HaltedZero; + bool HaltedOne; +}; + +struct RainParticle { + int x; + int y; + int fx; + int fy; + int life; + int trans; + bool active; + int translay; + int transhold; +}; + +struct MusicStream { + int volume; + const char *Filename; + int repeat; + stb_vorbis *Vorbis; + bool fix_click; +}; + +struct DustParticle { + int x; + int y; + int transp; + int life; + bool active; + int dx; + int dy; + int mlay; + int timlay; + int movedport; + int translay; + int translayHold; +}; + +struct Vars { + int screen_width = 640; + int screen_height = 360; + int screen_color_depth = 32; + AGSCharacter *playerCharacter = nullptr; + + SCAPI_CHARACTER_GETX Character_GetX = nullptr; + SCAPI_CHARACTER_GETY Character_GetY = nullptr; + SCAPI_CHARACTER_ID Character_ID = nullptr; + + getMus MusicLoads[80]; + Soundeffect SFX[500]; + RainParticle RainParticles[400]; + RainParticle RainParticlesFore[400]; + RainParticle RainParticlesBack[800]; + Aud GeneralAudio; + Mus MFXStream; + + int currentMusic = -1; + int currentMusicRepeat = -1; + int currentMusicFadein = 0; + + double xv[3]; + double yv[3]; + double xvOGG[3]; + double yvOGG[3]; + + int _x; + int _y; + int transp; + int life; + bool active; + int dx; + int dy; + int mlay; + int timlay; + int movedport; + int translay; + int translayHold; + int width; + int height; + int fx; + int fy; + bool doingcircle; + float angle; + float radius; + int doingCircleChance; + float angleLay; + int frame; + float anglespeed; + + Particle particles[110]; + Particle particlesF[10]; + Particle particles2[12]; + int WForceX[400]; + int WForceY[400]; + + int raysizeF = 4; + int dsizeF = 0; + int raysize = 100; + int dsize = 0; + int raysize2 = 12; + int dsize2 = 0; + int creationdelayf = 0; + int ww; + int hh; + int proom; + int prevroom; + bool OGG_Filter = false; + + SDL_AudioSpec spec[2]; + MusicStream globalStream[2]; + SDL_AudioDeviceID getDevice[2]; + bool AudioEnabled = false; + float ix, iy, ua; + float b_time[5]; + float d_time; + + // Y-coordinate first because we use horizontal scanlines + uint32 texture[texHeight][texWidth]; + int distanceTable[screenHeight][screenWidth]; + int angleTable[screenHeight][screenWidth]; + bool generateonce = false; + + DustParticle dusts[200]; + int waitBy = 6; + int raysizeDust = 200; + int dsizeDust = 0; + int creationdelay = 0; + int Walkbehind[20]; + char *GameDatavalue[40000]; + char *Token[10000]; + int TokenUnUsed[10000]; + int usedTokens = 0; + + int dY[30]; + int tDy[30]; + int direction[30]; +}; + +} // namespace AGSWaves +} // namespace Plugins +} // namespace AGS3 + +#endif