mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
Apparently, this field was used to store light level of the walkable area in pre-2.55 engines, prior to introduction of the Regions. In current engine, when loading games that old, this value is copied into Regions for backwards compatibility. While in newer games it actually stores "player character view" override. Renamed update_shadow_areas() into update_player_view(), and tidied the code for clarity. From upstream 71e7dc880b4496dd6937cec00a56f0de66137482
287 lines
7.2 KiB
C++
287 lines
7.2 KiB
C++
/* 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 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 "ags/shared/ac/common.h" // quit
|
|
#include "ags/shared/game/room_file.h"
|
|
#include "ags/shared/game/room_struct.h"
|
|
#include "ags/shared/gfx/bitmap.h"
|
|
|
|
namespace AGS3 {
|
|
namespace AGS {
|
|
namespace Shared {
|
|
|
|
RoomOptions::RoomOptions()
|
|
: StartupMusic(0)
|
|
, SaveLoadDisabled(false)
|
|
, PlayerCharOff(false)
|
|
, PlayerView(0)
|
|
, MusicVolume(kRoomVolumeNormal)
|
|
, Flags(0) {
|
|
}
|
|
|
|
RoomBgFrame::RoomBgFrame()
|
|
: IsPaletteShared(false) {
|
|
memset(Palette, 0, sizeof(Palette));
|
|
}
|
|
|
|
RoomEdges::RoomEdges()
|
|
: Left(0)
|
|
, Right(0)
|
|
, Top(0)
|
|
, Bottom(0) {
|
|
}
|
|
|
|
RoomEdges::RoomEdges(int l, int r, int t, int b)
|
|
: Left(l)
|
|
, Right(r)
|
|
, Top(t)
|
|
, Bottom(b) {
|
|
}
|
|
|
|
RoomObjectInfo::RoomObjectInfo()
|
|
: Sprite(0)
|
|
, X(0)
|
|
, Y(0)
|
|
, Room(-1)
|
|
, IsOn(false)
|
|
, Baseline(0xFF)
|
|
, Flags(0) {
|
|
}
|
|
|
|
RoomRegion::RoomRegion()
|
|
: Light(0)
|
|
, Tint(0) {
|
|
}
|
|
|
|
WalkArea::WalkArea()
|
|
: CharacterView(0)
|
|
, ScalingFar(0)
|
|
, ScalingNear(NOT_VECTOR_SCALED)
|
|
, PlayerView(0)
|
|
, Top(-1)
|
|
, Bottom(-1) {
|
|
}
|
|
|
|
WalkBehind::WalkBehind()
|
|
: Baseline(0) {
|
|
}
|
|
|
|
MessageInfo::MessageInfo()
|
|
: DisplayAs(0)
|
|
, Flags(0) {
|
|
}
|
|
|
|
RoomStruct::RoomStruct() {
|
|
InitDefaults();
|
|
}
|
|
|
|
RoomStruct::~RoomStruct() {
|
|
Free();
|
|
}
|
|
|
|
void RoomStruct::Free() {
|
|
for (size_t i = 0; i < (size_t)MAX_ROOM_BGFRAMES; ++i)
|
|
BgFrames[i].Graphic.reset();
|
|
HotspotMask.reset();
|
|
RegionMask.reset();
|
|
WalkAreaMask.reset();
|
|
WalkBehindMask.reset();
|
|
|
|
LocalVariables.clear();
|
|
Interaction.reset();
|
|
Properties.clear();
|
|
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i) {
|
|
Hotspots[i].Interaction.reset();
|
|
Hotspots[i].Properties.clear();
|
|
}
|
|
Objects.clear();
|
|
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i) {
|
|
Regions[i].Interaction.reset();
|
|
Regions[i].Properties.clear();
|
|
}
|
|
|
|
FreeMessages();
|
|
FreeScripts();
|
|
}
|
|
|
|
void RoomStruct::FreeMessages() {
|
|
for (size_t i = 0; i < MessageCount; ++i) {
|
|
Messages[i].Free();
|
|
MessageInfos[i] = MessageInfo();
|
|
}
|
|
MessageCount = 0;
|
|
}
|
|
|
|
void RoomStruct::FreeScripts() {
|
|
CompiledScript.reset();
|
|
|
|
EventHandlers.reset();
|
|
for (size_t i = 0; i < HotspotCount; ++i)
|
|
Hotspots[i].EventHandlers.reset();
|
|
for (auto &obj : Objects)
|
|
obj.EventHandlers.reset();
|
|
for (size_t i = 0; i < RegionCount; ++i)
|
|
Regions[i].EventHandlers.reset();
|
|
}
|
|
|
|
void RoomStruct::InitDefaults() {
|
|
DataVersion = kRoomVersion_Current;
|
|
GameID = NO_GAME_ID_IN_ROOM_FILE;
|
|
|
|
_resolution = kRoomRealRes;
|
|
MaskResolution = 1;
|
|
Width = 320;
|
|
Height = 200;
|
|
|
|
Options = RoomOptions();
|
|
Edges = RoomEdges(0, 317, 40, 199);
|
|
|
|
BgFrameCount = 1;
|
|
HotspotCount = 0;
|
|
RegionCount = 0;
|
|
WalkAreaCount = 0;
|
|
WalkBehindCount = 0;
|
|
MessageCount = 0;
|
|
|
|
for (size_t i = 0; i < (size_t)MAX_ROOM_HOTSPOTS; ++i)
|
|
Hotspots[i] = RoomHotspot();
|
|
for (size_t i = 0; i < (size_t)MAX_ROOM_REGIONS; ++i)
|
|
Regions[i] = RoomRegion();
|
|
for (size_t i = 0; i <= (size_t)MAX_WALK_AREAS; ++i)
|
|
WalkAreas[i] = WalkArea();
|
|
for (size_t i = 0; i < (size_t)MAX_WALK_BEHINDS; ++i)
|
|
WalkBehinds[i] = WalkBehind();
|
|
|
|
BackgroundBPP = 1;
|
|
BgAnimSpeed = 5;
|
|
|
|
memset(Palette, 0, sizeof(Palette));
|
|
}
|
|
|
|
void RoomStruct::SetResolution(RoomResolutionType type) {
|
|
_resolution = type;
|
|
}
|
|
|
|
Bitmap *RoomStruct::GetMask(RoomAreaMask mask) const {
|
|
switch (mask) {
|
|
case kRoomAreaHotspot: return HotspotMask.get();
|
|
case kRoomAreaWalkBehind: return WalkBehindMask.get();
|
|
case kRoomAreaWalkable: return WalkAreaMask.get();
|
|
case kRoomAreaRegion: return RegionMask.get();
|
|
default: return nullptr;
|
|
}
|
|
}
|
|
|
|
float RoomStruct::GetMaskScale(RoomAreaMask mask) const {
|
|
switch (mask) {
|
|
case kRoomAreaWalkBehind: return 1.f; // walk-behinds always 1:1 with room size
|
|
case kRoomAreaHotspot:
|
|
case kRoomAreaWalkable:
|
|
case kRoomAreaRegion:
|
|
return 1.f / MaskResolution;
|
|
default:
|
|
return 0.f;
|
|
}
|
|
}
|
|
|
|
bool RoomStruct::HasRegionLightLevel(int id) const {
|
|
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
|
return Regions[id].Tint == 0;
|
|
return false;
|
|
}
|
|
|
|
bool RoomStruct::HasRegionTint(int id) const {
|
|
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
|
return Regions[id].Tint != 0;
|
|
return false;
|
|
}
|
|
|
|
int RoomStruct::GetRegionLightLevel(int id) const {
|
|
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
|
return HasRegionLightLevel(id) ? Regions[id].Light : 0;
|
|
return 0;
|
|
}
|
|
|
|
int RoomStruct::GetRegionTintLuminance(int id) const {
|
|
if (id >= 0 && id < MAX_ROOM_REGIONS)
|
|
return HasRegionTint(id) ? (Regions[id].Light * 10) / 25 : 0;
|
|
return 0;
|
|
}
|
|
|
|
void load_room(const String &filename, RoomStruct *room, bool game_is_hires, const std::vector<SpriteInfo> &sprinfos) {
|
|
room->Free();
|
|
room->InitDefaults();
|
|
|
|
RoomDataSource src;
|
|
HRoomFileError err = OpenRoomFileFromAsset(filename, src);
|
|
if (err) {
|
|
err = ReadRoomData(room, src.InputStream.get(), src.DataVersion);
|
|
if (err)
|
|
err = UpdateRoomData(room, src.DataVersion, game_is_hires, sprinfos);
|
|
}
|
|
if (!err)
|
|
quitprintf("Unable to load the room file '%s'.\n%s.", filename.GetCStr(), err->FullMessage().GetCStr());
|
|
}
|
|
|
|
PBitmap FixBitmap(PBitmap bmp, int width, int height) {
|
|
Bitmap *new_bmp = BitmapHelper::AdjustBitmapSize(bmp.get(), width, height);
|
|
if (new_bmp != bmp.get())
|
|
return PBitmap(new_bmp);
|
|
return bmp;
|
|
}
|
|
|
|
void UpscaleRoomBackground(RoomStruct *room, bool game_is_hires) {
|
|
if (room->DataVersion >= kRoomVersion_303b || !game_is_hires)
|
|
return;
|
|
for (size_t i = 0; i < room->BgFrameCount; ++i)
|
|
room->BgFrames[i].Graphic = FixBitmap(room->BgFrames[i].Graphic, room->Width, room->Height);
|
|
FixRoomMasks(room);
|
|
}
|
|
|
|
void FixRoomMasks(RoomStruct *room) {
|
|
if (room->MaskResolution <= 0)
|
|
return;
|
|
Bitmap *bkg = room->BgFrames[0].Graphic.get();
|
|
if (bkg == nullptr)
|
|
return;
|
|
// TODO: this issue is somewhat complicated. Original code was relying on
|
|
// room->Width and Height properties. But in the engine these are saved
|
|
// already converted to data resolution which may be "low-res". Since this
|
|
// function is shared between engine and editor we do not know if we need
|
|
// to upscale them.
|
|
// For now room width/height is always equal to background bitmap.
|
|
int base_width = bkg->GetWidth();
|
|
int base_height = bkg->GetHeight();
|
|
int low_width = base_width / room->MaskResolution;
|
|
int low_height = base_height / room->MaskResolution;
|
|
|
|
// Walk-behinds are always 1:1 of the primary background.
|
|
// Other masks are 1:x where X is MaskResolution.
|
|
room->WalkBehindMask = FixBitmap(room->WalkBehindMask, base_width, base_height);
|
|
room->HotspotMask = FixBitmap(room->HotspotMask, low_width, low_height);
|
|
room->RegionMask = FixBitmap(room->RegionMask, low_width, low_height);
|
|
room->WalkAreaMask = FixBitmap(room->WalkAreaMask, low_width, low_height);
|
|
}
|
|
|
|
} // namespace Shared
|
|
} // namespace AGS
|
|
} // namespace AGS3
|