Files
sfall/sfall/Modules/Scripting/Handlers/Worldmap.cpp
T

279 lines
7.2 KiB
C++
Raw Normal View History

/*
* sfall
* Copyright (C) 2008-2016 The sfall team
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
#include "..\..\..\FalloutEngine\AsmMacros.h"
#include "..\..\..\FalloutEngine\Fallout2.h"
#include "..\..\..\SafeWrite.h"
#include "..\..\LoadGameHook.h"
#include "..\..\ScriptExtender.h"
#include "..\..\Worldmap.h"
#include "..\Arrays.h"
#include "..\OpcodeContext.h"
#include "Worldmap.h"
2017-03-05 21:49:21 +07:00
namespace sfall
{
namespace script
{
static DWORD ForceEncounterMapID = -1;
static DWORD ForceEncounterFlags;
DWORD ForceEncounterRestore() {
if (ForceEncounterMapID == -1) return 0;
__int64 data = 0x672E043D83; // cmp ds:_Meet_Frank_Horrigan, 0
SafeWriteBytes(0x4C06D1, (BYTE*)&data, 5);
ForceEncounterFlags = 0;
DWORD mapID = ForceEncounterMapID;
ForceEncounterMapID = -1;
return mapID;
}
2016-11-11 01:27:38 +07:00
static void ForceEncounterEffects() {
if (ForceEncounterFlags & 0x10) { // _FadeOut flag
__asm mov eax, FO_VAR_black_palette;
__asm call fo::funcoffs::palette_fade_to_;
return;
};
// implements a flashing encounter icon
if (ForceEncounterFlags & 4) return; // _NoIcon flag
long iconType = (ForceEncounterFlags & 8) ? 3 : 1; // icon type flag (special: 0-3, normal: 0-1)
2021-08-27 20:45:53 +08:00
fo::var::setInt(FO_VAR_wmEncounterIconShow) = 1;
fo::var::setInt(FO_VAR_wmRndCursorFid) = 0;
for (size_t n = 8; n > 0; --n) {
2021-08-27 20:45:53 +08:00
long iconFidIndex = iconType - fo::var::getInt(FO_VAR_wmRndCursorFid);
fo::var::setInt(FO_VAR_wmRndCursorFid) = iconFidIndex;
__asm call fo::funcoffs::wmInterfaceRefresh_;
fo::func::block_for_tocks(200);
}
2021-08-27 20:45:53 +08:00
fo::var::setInt(FO_VAR_wmEncounterIconShow) = 0;
}
static void __declspec(naked) wmRndEncounterOccurred_hack() {
__asm {
test ForceEncounterFlags, 0x1; // _NoCar flag
jnz noCar;
2022-11-30 14:27:46 +08:00
cmp dword ptr ds:[FO_VAR_Move_on_Car], 0;
jz noCar;
mov edx, FO_VAR_carCurrentArea;
mov eax, ForceEncounterMapID;
call fo::funcoffs::wmMatchAreaContainingMapIdx_;
noCar:
call ForceEncounterEffects;
call ForceEncounterRestore;
push 0x4C0721; // return addr
jmp fo::funcoffs::map_load_idx_; // eax - mapID
}
}
2016-11-11 01:27:38 +07:00
void op_force_encounter(OpcodeContext& cxt) {
if (ForceEncounterFlags & (1 << 31)) return; // wait prev. encounter
DWORD mapID = cxt.arg(0).rawValue();
if (mapID < 0) {
cxt.printOpcodeError("%s() - invalid map number.", cxt.getOpcodeName());
return;
}
if (ForceEncounterMapID == -1) MakeJump(0x4C06D1, wmRndEncounterOccurred_hack);
ForceEncounterMapID = mapID;
DWORD flags = 0;
if (cxt.numArgs() > 1) {
flags = cxt.arg(1).rawValue();
if (flags & 2) { // _Lock flag
flags |= (1 << 31); // set bit 31
} else {
flags &= ~(1 << 31);
}
}
ForceEncounterFlags = flags;
}
// world_map_functions
void __declspec(naked) op_in_world_map() {
__asm {
2019-12-04 10:39:35 +08:00
mov esi, ecx;
call InWorldMap;
mov edx, eax;
2019-11-28 14:05:36 +08:00
mov eax, ebx;
_RET_VAL_INT;
2019-12-04 10:39:35 +08:00
mov ecx, esi;
retn;
}
}
2016-11-11 01:27:38 +07:00
void __declspec(naked) op_get_game_mode() {
__asm {
2019-12-04 10:39:35 +08:00
mov esi, ecx;
call GetLoopFlags;
mov edx, eax;
2019-11-28 14:05:36 +08:00
mov eax, ebx;
_RET_VAL_INT;
2019-12-04 10:39:35 +08:00
mov ecx, esi;
retn;
}
}
2016-11-11 01:27:38 +07:00
void __declspec(naked) op_get_world_map_x_pos() {
__asm {
mov edx, ds:[FO_VAR_world_xpos];
2019-12-04 10:39:35 +08:00
_J_RET_VAL_TYPE(VAR_TYPE_INT);
// retn;
}
}
2016-11-11 01:27:38 +07:00
void __declspec(naked) op_get_world_map_y_pos() {
__asm {
mov edx, ds:[FO_VAR_world_ypos];
2019-12-04 10:39:35 +08:00
_J_RET_VAL_TYPE(VAR_TYPE_INT);
// retn;
}
}
2016-11-11 01:27:38 +07:00
void __declspec(naked) op_set_world_map_pos() {
__asm {
push ecx;
_GET_ARG(ecx, esi); // get y value
mov eax, ebx;
_GET_ARG_INT(end); // get x value
cmp si, VAR_TYPE_INT;
jne end;
mov ds:[FO_VAR_world_xpos], eax;
mov ds:[FO_VAR_world_ypos], ecx;
end:
pop ecx;
retn;
}
}
void op_set_map_time_multi(OpcodeContext& ctx) {
Worldmap::SetMapMulti(ctx.arg(0).asFloat());
}
void mf_set_car_intface_art(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
Worldmap::SetCarInterfaceArt(ctx.arg(0).rawValue());
}
void mf_set_map_enter_position(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
int tile = ctx.arg(0).rawValue();
int elev = ctx.arg(1).rawValue();
int rot = ctx.arg(2).rawValue();
2018-04-27 14:35:29 +03:00
if (tile > -1 && tile < 40000) {
2018-04-27 14:35:29 +03:00
fo::var::tile = tile;
}
if (elev > -1 && elev < 3) {
fo::var::elevation = elev;
}
if (rot > -1 && rot < 6) {
fo::var::rotation = rot;
}
}
void mf_get_map_enter_position(OpcodeContext& ctx) {
2020-10-12 11:01:25 +08:00
DWORD id = CreateTempArray(3, 0);
2018-04-27 14:35:29 +03:00
arrays[id].val[0].set((long)fo::var::tile);
arrays[id].val[1].set((long)fo::var::elevation);
arrays[id].val[2].set((long)fo::var::rotation);
2019-11-28 14:05:36 +08:00
ctx.setReturn(id);
2018-04-27 14:35:29 +03:00
}
void mf_set_rest_heal_time(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
Worldmap::SetRestHealTime(ctx.arg(0).rawValue());
2018-05-08 07:18:44 +03:00
}
void mf_set_rest_mode(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
Worldmap::SetRestMode(ctx.arg(0).rawValue());
2018-05-08 07:18:44 +03:00
}
void mf_set_rest_on_map(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
long mapId = ctx.arg(0).rawValue();
if (mapId < 0) {
ctx.printOpcodeError("%s() - invalid map number argument.", ctx.getMetaruleName());
2019-11-28 14:05:36 +08:00
ctx.setReturn(-1);
return;
}
2019-11-28 14:05:36 +08:00
long elev = ctx.arg(1).rawValue();
if (elev < -1 || elev > 2) {
ctx.printOpcodeError("%s() - invalid map elevation argument.", ctx.getMetaruleName());
2019-11-28 14:05:36 +08:00
ctx.setReturn(-1);
} else {
Worldmap::SetRestMapLevel(mapId, elev, ctx.arg(2).asBool());
}
}
void mf_get_rest_on_map(OpcodeContext& ctx) {
2019-11-28 14:05:36 +08:00
long result = -1;
long elev = ctx.arg(1).rawValue();
if (elev < 0 || elev > 2) {
ctx.printOpcodeError("%s() - invalid map elevation argument.", ctx.getMetaruleName());
} else {
2019-11-28 14:05:36 +08:00
result = Worldmap::GetRestMapLevel(elev, ctx.arg(0).rawValue());
}
2019-11-28 14:05:36 +08:00
ctx.setReturn(result);
}
void mf_tile_by_position(OpcodeContext& ctx) {
2019-12-11 15:52:03 +08:00
ctx.setReturn(fo::func::tile_num(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()));
}
2022-06-14 21:04:51 +08:00
static const char* invalidSubTilePos = "%s() - invalid x/y coordinates for the sub-tile.";
void mf_set_terrain_name(OpcodeContext& ctx) {
2022-06-14 21:04:51 +08:00
long x = ctx.arg(0).rawValue();
long y = ctx.arg(1).rawValue();
if (x < 0 || x >= (long)(7 * fo::var::wmNumHorizontalTiles) ||
y < 0 || y >= (long)(6 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)))
{
ctx.printOpcodeError(invalidSubTilePos, ctx.getMetaruleName());
} else {
Worldmap::SetTerrainTypeName(x, y, ctx.arg(2).strValue());
}
}
void mf_get_terrain_name(OpcodeContext& ctx) {
if (ctx.numArgs() < 2) {
ctx.setReturn(Worldmap::GetCurrentTerrainName());
} else {
long x = ctx.arg(0).rawValue();
long y = ctx.arg(1).rawValue();
if (x < 0 || x >= (long)(7 * fo::var::wmNumHorizontalTiles) ||
y < 0 || y >= (long)(6 * (fo::var::wmMaxTileNum / fo::var::wmNumHorizontalTiles)))
{
ctx.printOpcodeError(invalidSubTilePos, ctx.getMetaruleName());
ctx.setReturn("Error");
} else {
ctx.setReturn(Worldmap::GetTerrainTypeName(x, y));
}
}
2020-01-18 17:28:05 +08:00
}
void mf_set_town_title(OpcodeContext& ctx) {
2020-01-25 15:47:57 +08:00
Worldmap::SetCustomAreaTitle(ctx.arg(0).rawValue(), ctx.arg(1).strValue());
}
2017-03-05 21:49:21 +07:00
}
}