dxx-rebirth/similar/main/paging.cpp

376 lines
11 KiB
C++
Raw Normal View History

2006-03-20 16:43:15 +00:00
/*
2014-06-01 17:55:23 +00:00
* Portions of this file are copyright Rebirth contributors and licensed as
* described in COPYING.txt.
* Portions of this file are copyright Parallax Software and licensed
* according to the Parallax license below.
* See COPYING.txt for license details.
2006-03-20 16:43:15 +00:00
THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
2006-03-20 16:43:15 +00:00
*/
2006-03-20 16:43:15 +00:00
/*
*
* Routines for paging in/out textures.
2006-03-20 16:43:15 +00:00
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "pstypes.h"
2006-03-20 16:43:15 +00:00
#include "inferno.h"
#include "segment.h"
#include "textures.h"
#include "wall.h"
#include "object.h"
#include "console.h"
2006-03-20 16:43:15 +00:00
#include "game.h"
#include "piggy.h"
#include "texmerge.h"
#include "paging.h"
#include "robot.h"
2006-03-20 16:43:15 +00:00
#include "vclip.h"
#include "effects.h"
#include "fireball.h"
#include "weapon.h"
#include "palette.h"
#include "text.h"
#include "gauges.h"
#include "powerup.h"
#include "fuelcen.h"
#include "ai.h"
2014-04-27 23:12:34 +00:00
#include "compiler-range_for.h"
#include "d_levelstate.h"
2014-04-27 23:12:34 +00:00
#include "partial_range.h"
#include "segiter.h"
2006-03-20 16:43:15 +00:00
namespace {
static void paging_touch_vclip(const vclip &vc, const unsigned line)
#define paging_touch_vclip(V) paging_touch_vclip(V, __LINE__)
2006-03-20 16:43:15 +00:00
{
using range_type = partial_range_t<const bitmap_index*>;
union {
uint8_t storage[1];
range_type r;
} u{};
try
{
new(&u.r) range_type(partial_const_range<partial_range_detail::required_buffer_size<sizeof(__FILE__), sizeof("vc.frames")>>(__FILE__, line, "vc.frames", vc.frames, vc.num_frames));
static_assert(std::is_trivially_destructible<range_type>::value, "partial_range destructor not called");
}
catch (const range_type::partial_range_error &e)
{
con_puts(CON_URGENT, e.what());
return;
}
range_for (auto &i, u.r)
2014-09-20 23:47:27 +00:00
{
PIGGY_PAGE_IN(i);
2006-03-20 16:43:15 +00:00
}
}
2018-10-21 00:24:07 +00:00
static void paging_touch_wall_effects(const d_eclip_array &Effects, const Textures_array &Textures, const d_vclip_array &Vclip, const int tmap_num)
2006-03-20 16:43:15 +00:00
{
2016-02-12 04:02:28 +00:00
range_for (auto &i, partial_const_range(Effects, Num_effects))
2014-09-20 23:47:27 +00:00
{
if ( i.changing_wall_texture == tmap_num ) {
2015-08-22 20:43:03 +00:00
paging_touch_vclip(i.vc);
2006-03-20 16:43:15 +00:00
if (i.dest_bm_num < Textures.size())
2014-09-20 23:47:27 +00:00
PIGGY_PAGE_IN( Textures[i.dest_bm_num] ); //use this bitmap when monitor destroyed
if ( i.dest_vclip > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[i.dest_vclip]); //what vclip to play when exploding
2006-03-20 16:43:15 +00:00
2014-09-20 23:47:27 +00:00
if ( i.dest_eclip > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Effects[i.dest_eclip].vc); //what eclip to play when exploding
2006-03-20 16:43:15 +00:00
2014-09-20 23:47:27 +00:00
if ( i.crit_clip > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Effects[i.crit_clip].vc); //what eclip to play when mine critical
break;
2006-03-20 16:43:15 +00:00
}
}
}
static void paging_touch_object_effects(const d_eclip_array &Effects, const object_bitmap_index tmap_num)
2006-03-20 16:43:15 +00:00
{
2016-02-12 04:02:28 +00:00
range_for (auto &i, partial_const_range(Effects, Num_effects))
2014-09-20 23:47:27 +00:00
{
if ( i.changing_object_texture == tmap_num ) {
2015-08-22 20:43:03 +00:00
paging_touch_vclip(i.vc);
break;
2006-03-20 16:43:15 +00:00
}
}
}
2013-10-27 22:00:14 +00:00
static void paging_touch_model( int modelnum )
2006-03-20 16:43:15 +00:00
{
auto &Effects = LevelUniqueEffectsClipState.Effects;
auto &Polygon_models = LevelSharedPolygonModelState.Polygon_models;
2015-08-22 20:43:03 +00:00
const auto &pm = Polygon_models[modelnum];
const uint_fast32_t b = pm.first_texture;
const uint_fast32_t e = b + pm.n_textures;
range_for (const auto p, partial_range(ObjBitmapPtrs, b, e))
2015-08-22 20:43:03 +00:00
{
PIGGY_PAGE_IN(ObjBitmaps[p]);
paging_touch_object_effects(Effects, p);
2006-03-20 16:43:15 +00:00
}
}
2018-10-21 00:24:07 +00:00
static void paging_touch_weapon(const d_vclip_array &Vclip, const weapon_info &weapon)
2006-03-20 16:43:15 +00:00
{
// Page in the robot's weapons.
2015-08-22 20:43:03 +00:00
if(weapon.picture.index)
{
PIGGY_PAGE_IN(weapon.picture);
2006-03-20 16:43:15 +00:00
}
2015-08-22 20:43:03 +00:00
if (weapon.flash_vclip > -1)
paging_touch_vclip(Vclip[weapon.flash_vclip]);
if (weapon.wall_hit_vclip > -1)
paging_touch_vclip(Vclip[weapon.wall_hit_vclip]);
if (weapon.damage_radius)
{
2006-03-20 16:43:15 +00:00
// Robot_hit_vclips are actually badass_vclips
2015-08-22 20:43:03 +00:00
if (weapon.robot_hit_vclip > -1)
paging_touch_vclip(Vclip[weapon.robot_hit_vclip]);
2006-03-20 16:43:15 +00:00
}
switch(weapon.render)
2015-08-22 20:43:03 +00:00
{
2006-03-20 16:43:15 +00:00
case WEAPON_RENDER_VCLIP:
2015-08-22 20:43:03 +00:00
if (weapon.weapon_vclip > -1)
paging_touch_vclip(Vclip[weapon.weapon_vclip]);
2006-03-20 16:43:15 +00:00
break;
case WEAPON_RENDER_NONE:
case weapon_info::render_type::laser:
2006-03-20 16:43:15 +00:00
break;
case WEAPON_RENDER_POLYMODEL:
2015-08-22 20:43:03 +00:00
paging_touch_model(weapon.model_num);
2006-03-20 16:43:15 +00:00
break;
case WEAPON_RENDER_BLOB:
2015-08-22 20:43:03 +00:00
PIGGY_PAGE_IN(weapon.bitmap);
2006-03-20 16:43:15 +00:00
break;
}
}
2018-10-21 00:24:07 +00:00
static void paging_touch_weapon(const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const uint_fast32_t weapon_type)
2015-08-22 20:43:03 +00:00
{
if (weapon_type < N_weapon_types)
2018-10-21 00:24:07 +00:00
paging_touch_weapon(Vclip, Weapon_info[weapon_type]);
2015-08-22 20:43:03 +00:00
}
2020-05-02 21:18:42 +00:00
const std::array<sbyte, 13> super_boss_gate_type_list{{0, 1, 8, 9, 10, 11, 12, 15, 16, 18, 19, 20, 22}};
2006-03-20 16:43:15 +00:00
static void paging_touch_robot(const d_robot_info_array &Robot_info, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const unsigned ridx)
2006-03-20 16:43:15 +00:00
{
2018-10-21 00:24:07 +00:00
auto &ri = Robot_info[ridx];
2006-03-20 16:43:15 +00:00
// Page in robot_index
2015-08-22 20:43:03 +00:00
paging_touch_model(ri.model_num);
if (ri.exp1_vclip_num > -1)
paging_touch_vclip(Vclip[ri.exp1_vclip_num]);
if (ri.exp2_vclip_num > -1)
paging_touch_vclip(Vclip[ri.exp2_vclip_num]);
2006-03-20 16:43:15 +00:00
// Page in his weapons
2018-10-21 00:24:07 +00:00
paging_touch_weapon(Vclip, Weapon_info, ri.weapon_type);
2006-03-20 16:43:15 +00:00
// A super-boss can gate in robots...
2015-08-22 20:43:03 +00:00
if (ri.boss_flag == BOSS_SUPER)
{
2015-02-14 22:48:27 +00:00
range_for (const auto i, super_boss_gate_type_list)
2018-10-21 00:24:07 +00:00
paging_touch_robot(Robot_info, Vclip, Weapon_info, i);
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[VCLIP_MORPHING_ROBOT]);
2006-03-20 16:43:15 +00:00
}
}
static void paging_touch_object(const d_robot_info_array &Robot_info, const Textures_array &Textures, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const object_base &obj)
2006-03-20 16:43:15 +00:00
{
int v;
switch (obj.render_type) {
2006-03-20 16:43:15 +00:00
case RT_NONE: break; //doesn't render, like the player
case RT_POLYOBJ:
if (obj.rtype.pobj_info.tmap_override != -1)
PIGGY_PAGE_IN(Textures[obj.rtype.pobj_info.tmap_override]);
else
paging_touch_model(obj.rtype.pobj_info.model_num);
2006-03-20 16:43:15 +00:00
break;
case RT_POWERUP:
if (obj.rtype.vclip_info.vclip_num > -1)
{
paging_touch_vclip(Vclip[obj.rtype.vclip_info.vclip_num]);
}
2006-03-20 16:43:15 +00:00
break;
case RT_MORPH: break;
case RT_FIREBALL: break;
case RT_WEAPON_VCLIP: break;
case RT_HOSTAGE:
paging_touch_vclip(Vclip[obj.rtype.vclip_info.vclip_num]);
2006-03-20 16:43:15 +00:00
break;
case RT_LASER: break;
}
switch (obj.type) {
2016-11-20 23:12:00 +00:00
default:
break;
2006-03-20 16:43:15 +00:00
case OBJ_PLAYER:
v = get_explosion_vclip(LevelSharedRobotInfoState.Robot_info, obj, explosion_vclip_stage::s0);
2006-03-20 16:43:15 +00:00
if ( v > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[v]);
2006-03-20 16:43:15 +00:00
break;
case OBJ_ROBOT:
2018-10-21 00:24:07 +00:00
paging_touch_robot(Robot_info, Vclip, Weapon_info, get_robot_id(obj));
2006-03-20 16:43:15 +00:00
break;
case OBJ_CNTRLCEN:
2018-10-21 00:24:07 +00:00
paging_touch_weapon(Vclip, Weapon_info, weapon_id_type::CONTROLCEN_WEAPON_NUM);
if (Dead_modelnums[obj.rtype.pobj_info.model_num] != -1)
{
paging_touch_model(Dead_modelnums[obj.rtype.pobj_info.model_num]);
2006-03-20 16:43:15 +00:00
}
break;
}
}
static void paging_touch_side(const d_eclip_array &Effects, const Textures_array &Textures, const d_vclip_array &Vclip, const cscusegment segp, const sidenum_t sidenum)
2006-03-20 16:43:15 +00:00
{
auto &Walls = LevelUniqueWallSubsystemState.Walls;
auto &vcwallptr = Walls.vcptr;
if (!(WALL_IS_DOORWAY(GameBitmaps, Textures, vcwallptr, segp, sidenum) & WALL_IS_DOORWAY_FLAG::render))
2006-03-20 16:43:15 +00:00
return;
auto &uside = segp.u.sides[sidenum];
2018-12-13 02:31:38 +00:00
const auto tmap1 = uside.tmap_num;
2020-09-11 03:08:02 +00:00
paging_touch_wall_effects(Effects, Textures, Vclip, get_texture_index(tmap1));
if (const auto tmap2 = uside.tmap_num2; tmap2 != texture2_value::None)
{
2006-03-20 16:43:15 +00:00
texmerge_get_cached_bitmap( tmap1, tmap2 );
paging_touch_wall_effects(Effects, Textures, Vclip, get_texture_index(tmap2));
2006-03-20 16:43:15 +00:00
} else {
2020-09-11 03:08:02 +00:00
PIGGY_PAGE_IN(Textures[get_texture_index(tmap1)]);
2006-03-20 16:43:15 +00:00
}
}
static void paging_touch_robot_maker(const d_robot_info_array &Robot_info, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const shared_segment &segp)
2006-03-20 16:43:15 +00:00
{
auto &RobotCenters = LevelSharedRobotcenterState.RobotCenters;
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[VCLIP_MORPHING_ROBOT]);
2018-10-21 00:24:07 +00:00
const auto &robot_flags = RobotCenters[segp.matcen_num].robot_flags;
2015-08-22 20:43:03 +00:00
const std::size_t bits_per_robot_flags = 8 * sizeof(robot_flags[0]);
for (uint_fast32_t i = 0; i != robot_flags.size(); ++i)
{
auto robot_index = i * bits_per_robot_flags;
uint_fast32_t flags = robot_flags[i];
if (sizeof(flags) >= 2 * sizeof(robot_flags[0]) && i + 1 != robot_flags.size())
flags |= static_cast<uint64_t>(robot_flags[++i]) << bits_per_robot_flags;
while (flags) {
if (flags & 1) {
// Page in robot_index
2018-10-21 00:24:07 +00:00
paging_touch_robot(Robot_info, Vclip, Weapon_info, robot_index);
}
flags >>= 1;
robot_index++;
2006-03-20 16:43:15 +00:00
}
}
2006-03-20 16:43:15 +00:00
}
static void paging_touch_segment(const d_eclip_array &Effects, const d_robot_info_array &Robot_info, const Textures_array &Textures, const d_vclip_array &Vclip, const weapon_info_array &Weapon_info, const fvcobjptridx &vcobjptridx, const fvcsegptr &vcsegptr, const cscusegment segp)
2006-03-20 16:43:15 +00:00
{
2021-11-01 03:37:19 +00:00
if (segp.s.special == segment_special::robotmaker)
2018-10-21 00:24:07 +00:00
paging_touch_robot_maker(Robot_info, Vclip, Weapon_info, segp);
2006-03-20 16:43:15 +00:00
for (const auto sn : MAX_SIDES_PER_SEGMENT)
{
2018-10-21 00:24:07 +00:00
paging_touch_side(Effects, Textures, Vclip, segp, sn);
2006-03-20 16:43:15 +00:00
}
range_for (const object &objp, objects_in(segp, vcobjptridx, vcsegptr))
2018-10-21 00:24:07 +00:00
paging_touch_object(Robot_info, Textures, Vclip, Weapon_info, objp);
2006-03-20 16:43:15 +00:00
}
2018-10-21 00:24:07 +00:00
static void paging_touch_walls(const Textures_array &Textures, const wall_animations_array &WallAnims, const fvcwallptr &vcwallptr)
2006-03-20 16:43:15 +00:00
{
2016-02-12 04:02:28 +00:00
range_for (const auto &&wp, vcwallptr)
2014-04-27 23:12:34 +00:00
{
2016-02-12 04:02:28 +00:00
auto &w = *wp;
2014-04-27 23:12:34 +00:00
if ( w.clip_num > -1 ) {
2017-06-17 23:05:16 +00:00
const auto &anim = WallAnims[w.clip_num];
range_for (auto &j, partial_range(anim.frames, anim.num_frames))
PIGGY_PAGE_IN(Textures[j]);
2006-03-20 16:43:15 +00:00
}
}
}
}
2006-03-20 16:43:15 +00:00
namespace dsx {
2018-10-21 00:24:07 +00:00
void paging_touch_all(const d_vclip_array &Vclip)
2006-03-20 16:43:15 +00:00
{
auto &Effects = LevelUniqueEffectsClipState.Effects;
auto &Objects = LevelUniqueObjectState.Objects;
auto &WallAnims = GameSharedState.WallAnims;
auto &vcobjptridx = Objects.vcptridx;
pause_game_world_time p;
2006-03-20 16:43:15 +00:00
#if defined(DXX_BUILD_DESCENT_I)
2021-09-12 16:20:52 +00:00
gr_set_default_canvas();
show_boxed_message(*grd_curcanv, TXT_LOADING);
gr_flip();
#endif
auto &Robot_info = LevelSharedRobotInfoState.Robot_info;
2016-02-12 04:02:28 +00:00
range_for (const auto &&segp, vcsegptr)
2014-10-12 23:10:05 +00:00
{
2018-10-21 00:24:07 +00:00
paging_touch_segment(Effects, Robot_info, Textures, Vclip, Weapon_info, vcobjptridx, vcsegptr, segp);
2006-03-20 16:43:15 +00:00
}
auto &Walls = LevelUniqueWallSubsystemState.Walls;
auto &vcwallptr = Walls.vcptr;
2018-10-21 00:24:07 +00:00
paging_touch_walls(Textures, WallAnims, vcwallptr);
2006-03-20 16:43:15 +00:00
2016-02-12 04:02:28 +00:00
range_for (auto &s, partial_const_range(Powerup_info, N_powerup_types))
2014-09-20 23:47:27 +00:00
{
if ( s.vclip_num > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[s.vclip_num]);
2006-03-20 16:43:15 +00:00
}
2016-02-12 04:02:28 +00:00
range_for (auto &w, partial_const_range(Weapon_info, N_weapon_types))
2015-08-22 20:43:03 +00:00
{
2018-10-21 00:24:07 +00:00
paging_touch_weapon(Vclip, w);
2006-03-20 16:43:15 +00:00
}
2016-02-12 04:02:28 +00:00
range_for (auto &s, partial_const_range(Powerup_info, N_powerup_types))
2014-09-20 23:47:27 +00:00
{
if ( s.vclip_num > -1 )
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[s.vclip_num]);
2006-03-20 16:43:15 +00:00
}
2014-09-20 23:47:27 +00:00
range_for (auto &s, Gauges)
{
if ( s.index ) {
PIGGY_PAGE_IN( s );
2006-03-20 16:43:15 +00:00
}
}
2015-08-22 20:43:03 +00:00
paging_touch_vclip(Vclip[VCLIP_PLAYER_APPEARANCE]);
paging_touch_vclip(Vclip[VCLIP_POWERUP_DISAPPEARANCE]);
2006-03-20 16:43:15 +00:00
reset_cockpit(); //force cockpit redraw next time
}
}