Files
fs2open.github.com/fred2/shipspecialdamage.cpp
Fabian Woltermann 770fce8de5 Bitset flags -- take 2 (#775)
This introduces a new mechanism for handling bit flags. Instead of using an int (or two, or three) to write bits into, this uses the std::bitset in a wrapper class that accepts an enum class as input. This means that certain classes of errors we've had a few of in the engine, where a coder used the wrong set of flags or checked them against the wrong variable (SF_STEALTH vs SIF_STEALTH, for example) can now be detected at a compiler level rather than not at all.
2016-08-12 16:13:50 -07:00

251 lines
6.7 KiB
C++

/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
// ShipSpecialDamage.cpp : implementation file
//
#include "stdafx.h"
#include "FRED.h"
#include "ShipSpecialDamage.h"
#include "globalincs/linklist.h"
#include "parse/sexp.h"
#include "FREDDoc.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// ShipSpecialDamage dialog
ShipSpecialDamage::ShipSpecialDamage(CWnd* pParent /*=NULL*/)
: CDialog(ShipSpecialDamage::IDD, pParent)
{
//{{AFX_DATA_INIT(ShipSpecialDamage)
//}}AFX_DATA_INIT
}
void ShipSpecialDamage::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(ShipSpecialDamage)
DDX_Check(pDX, IDC_ENABLE_SHOCKWAVE, m_shock_enabled);
DDX_Check(pDX, IDC_ENABLE_DEATHROLL_TIME, m_duration_enabled);
DDX_Check(pDX, IDC_ENABLE_SPECIAL_EXP, m_special_exp_enabled);
DDX_Text(pDX, IDC_SPECIAL_INNER_RAD, m_inner_rad);
DDV_MinMaxInt(pDX, m_inner_rad, 1, INT_MAX);
DDX_Text(pDX, IDC_SPECIAL_OUTER_RAD, m_outer_rad);
DDV_MinMaxInt(pDX, m_outer_rad, 2, INT_MAX);
DDX_Text(pDX, IDC_SPECIAL_DAMAGE, m_damage);
DDV_MinMaxInt(pDX, m_damage, 0, INT_MAX);
DDX_Text(pDX, IDC_SPECIAL_SHOCK_SPEED, m_shock_speed);
DDV_MinMaxInt(pDX, m_shock_speed, 0, INT_MAX);
DDX_Text(pDX, IDC_SPECIAL_DEATHROLL_TIME, m_duration);
DDV_MinMaxInt(pDX, m_duration, 0, INT_MAX);
DDX_Text(pDX, IDC_SPECIAL_BLAST, m_blast);
DDV_MinMaxInt(pDX, m_blast, 0, INT_MAX);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(ShipSpecialDamage, CDialog)
//{{AFX_MSG_MAP(ShipSpecialDamage)
ON_BN_CLICKED(IDC_ENABLE_SHOCKWAVE, OnEnableShockwave)
ON_BN_CLICKED(IDC_ENABLE_DEATHROLL_TIME, OnEnableDeathrollTime)
ON_BN_CLICKED(IDC_ENABLE_SPECIAL_EXP, OnEnableSpecialExp)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// ShipSpecialDamage message handlers
void ShipSpecialDamage::OnEnableShockwave()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
// enable/disable shock speed
DoGray();
}
void ShipSpecialDamage::OnEnableDeathrollTime()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
// set delay
m_duration = m_duration_enabled ? 2 : 0;
UpdateData(FALSE);
// enable/disable deathroll time
DoGray();
}
void ShipSpecialDamage::OnEnableSpecialExp()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
DoGray();
}
BOOL ShipSpecialDamage::OnInitDialog()
{
// TODO: Add extra initialization here
// get ship num
object *objp;
num_selected_ships = 0;
objp = GET_FIRST(&obj_used_list);
while (objp != END_OF_LIST(&obj_used_list)) {
if ((objp->type == OBJ_START) || (objp->type == OBJ_SHIP)) {
if (objp->flags[Object::Object_Flags::Marked]) {
m_selected_ships[num_selected_ships] = objp->instance;
num_selected_ships++;
}
}
objp = GET_NEXT(objp);
}
Assert (Objects[cur_object_index].flags[Object::Object_Flags::Marked]);
m_ship_num = Objects[cur_object_index].instance;
if (!(Ships[m_ship_num].use_special_explosion)) {
// get default_table_values
ship_info *sip;
sip = &Ship_info[Ships[m_ship_num].ship_info_index];
m_inner_rad = (int)sip->shockwave.inner_rad;
m_outer_rad = (int)sip->shockwave.outer_rad;
m_damage = (int) sip->shockwave.damage;
m_blast = (int) sip->shockwave.blast;
m_shock_enabled = (int) sip->explosion_propagates;
m_shock_speed = (int) sip->shockwave.speed;
m_duration_enabled = FALSE;
m_duration = 0;
m_special_exp_enabled = FALSE;
if (m_inner_rad < 1) {
m_inner_rad = 1;
}
if (m_outer_rad < 2) {
m_outer_rad = 2;
}
if (m_shock_speed < 1) {
m_shock_speed = 1;
}
}
else {
m_inner_rad = Ships[m_ship_num].special_exp_inner;
m_outer_rad = Ships[m_ship_num].special_exp_outer;
m_damage = Ships[m_ship_num].special_exp_damage;
m_blast = Ships[m_ship_num].special_exp_blast;
m_shock_enabled = Ships[m_ship_num].use_shockwave;
m_shock_speed = Ships[m_ship_num].special_exp_shockwave_speed;
m_duration_enabled = (Ships[m_ship_num].special_exp_deathroll_time > 0);
m_duration = Ships[m_ship_num].special_exp_deathroll_time;
m_special_exp_enabled = TRUE;
}
CDialog::OnInitDialog();
// maybe gray out lots of stuff
DoGray();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void ShipSpecialDamage::DoGray()
{
GetDlgItem(IDC_SPECIAL_DAMAGE)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_SPECIAL_BLAST)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_SPECIAL_INNER_RAD)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_SPECIAL_OUTER_RAD)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_ENABLE_SHOCKWAVE)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_ENABLE_DEATHROLL_TIME)->EnableWindow(m_special_exp_enabled);
GetDlgItem(IDC_SPECIAL_SHOCK_SPEED)->EnableWindow(m_special_exp_enabled && m_shock_enabled);
GetDlgItem(IDC_SPECIAL_DEATHROLL_TIME)->EnableWindow(m_special_exp_enabled && m_duration_enabled);
}
void ShipSpecialDamage::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
void ShipSpecialDamage::OnOK()
{
UpdateData(TRUE);
int i;
if (m_inner_rad > m_outer_rad) {
MessageBox("Inner radius must be less than outer radius");
return;
}
for ( i = 0; i < num_selected_ships; i++ ) {
update_ship(m_selected_ships[i]);
}
CDialog::OnOK();
}
void ShipSpecialDamage::update_ship(int shipnum)
{
ship *shipp = &Ships[shipnum];
// set to update
set_modified();
if (m_special_exp_enabled) {
// set em
shipp->use_special_explosion = true;
shipp->special_exp_inner = m_inner_rad;
shipp->special_exp_outer = m_outer_rad;
shipp->special_exp_damage = m_damage;
shipp->special_exp_blast = m_blast;
shipp->use_shockwave = (m_shock_enabled ? 1:0) ;
if (m_shock_speed) {
if (m_shock_speed < 1) {
m_shock_speed = 1;
MessageBox("Shockwave speed must be defined! Setting this to 1 now");
}
shipp->special_exp_shockwave_speed = m_shock_speed;
}
if (m_duration) {
if (m_duration < 2) {
m_duration = 2;
MessageBox("Death roll time must be at least 2 milliseconds!");
}
shipp->special_exp_deathroll_time = m_duration;
}
} else {
shipp->use_special_explosion = false;
shipp->special_exp_inner = -1;
shipp->special_exp_outer = -1;
shipp->special_exp_damage = -1;
shipp->special_exp_blast = -1;
shipp->use_shockwave = false;
shipp->special_exp_shockwave_speed = -1;
shipp->special_exp_deathroll_time = 0;
}
}