mirror of
https://github.com/electronicarts/CNC_TS_and_RA2_Mission_Editor.git
synced 2025-04-30 09:01:41 -04:00
616 lines
14 KiB
C++
616 lines
14 KiB
C++
/*
|
||
FinalSun/FinalAlert 2 Mission Editor
|
||
|
||
Copyright (C) 1999-2024 Electronic Arts, Inc.
|
||
Authored by Matthias Wagner
|
||
|
||
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 <https://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
// TriggerEventsDlg.cpp: Implementierungsdatei
|
||
//
|
||
|
||
#include "stdafx.h"
|
||
#include "finalsun.h"
|
||
#include "TriggerEventsDlg.h"
|
||
#include "mapdata.h"
|
||
#include "variables.h"
|
||
#include "functions.h"
|
||
#include "inlines.h"
|
||
|
||
#ifdef _DEBUG
|
||
#define new DEBUG_NEW
|
||
#undef THIS_FILE
|
||
static char THIS_FILE[] = __FILE__;
|
||
#endif
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Dialogfeld CTriggerEventsDlg
|
||
|
||
|
||
CTriggerEventsDlg::CTriggerEventsDlg(CWnd* pParent /*=NULL*/)
|
||
: CDialog(CTriggerEventsDlg::IDD, pParent)
|
||
{
|
||
//{{AFX_DATA_INIT(CTriggerEventsDlg)
|
||
// HINWEIS: Der Klassen-Assistent fügt hier Elementinitialisierung ein
|
||
//}}AFX_DATA_INIT
|
||
}
|
||
|
||
BOOL CTriggerEventsDlg::OnInitDialog()
|
||
{
|
||
auto const ret = CDialog::OnInitDialog();
|
||
|
||
TranslateUI();
|
||
|
||
return ret;
|
||
}
|
||
|
||
void CTriggerEventsDlg::DoDataExchange(CDataExchange* pDX)
|
||
{
|
||
CDialog::DoDataExchange(pDX);
|
||
//{{AFX_DATA_MAP(CTriggerEventsDlg)
|
||
DDX_Control(pDX, IDC_PARAMVALUE, m_ParamValue);
|
||
DDX_Control(pDX, IDC_PARAMETER, m_Parameter);
|
||
DDX_Control(pDX, IDC_EVENTTYPE, m_EventType);
|
||
DDX_Control(pDX, IDC_EVENTDESCRIPTION, m_EventDescription);
|
||
DDX_Control(pDX, IDC_EVENT, m_Event);
|
||
//}}AFX_DATA_MAP
|
||
}
|
||
|
||
|
||
BEGIN_MESSAGE_MAP(CTriggerEventsDlg, CDialog)
|
||
//{{AFX_MSG_MAP(CTriggerEventsDlg)
|
||
ON_BN_CLICKED(IDC_NEWEVENT, OnNewevent)
|
||
ON_BN_CLICKED(IDC_DELETEEVENT, OnDeleteevent)
|
||
ON_CBN_SELCHANGE(IDC_EVENT, OnSelchangeEvent)
|
||
ON_CBN_EDITCHANGE(IDC_EVENTTYPE, OnEditchangeEventtype)
|
||
ON_LBN_SELCHANGE(IDC_PARAMETER, OnSelchangeParameter)
|
||
ON_CBN_EDITCHANGE(IDC_PARAMVALUE, OnEditchangeParamvalue)
|
||
//}}AFX_MSG_MAP
|
||
END_MESSAGE_MAP()
|
||
|
||
void CTriggerEventsDlg::TranslateUI()
|
||
{
|
||
TranslateDlgItem(*this, IDC_EVENT_CUR_TXT, "TriggerEventCurrent");
|
||
TranslateDlgItem(*this, IDC_NEWEVENT, "TriggerEventNew");
|
||
TranslateDlgItem(*this, IDC_DELETEEVENT, "TriggerEventDelete");
|
||
TranslateDlgItem(*this, IDC_EVENT_OPT_TXT, "TriggerEventOptions");
|
||
TranslateDlgItem(*this, IDC_EVENT_TYPE_TXT, "TriggerEventType");
|
||
TranslateDlgItem(*this, IDC_EVENT_PARAM_TXT, "TriggerEventParams");
|
||
TranslateDlgItem(*this, IDC_EVENT_VAL_TXT, "TriggerEventParamValue");
|
||
TranslateDlgItem(*this, IDC_EVENT_DESC, "TriggerEventDesc");
|
||
}
|
||
|
||
/////////////////////////////////////////////////////////////////////////////
|
||
// Behandlungsroutinen für Nachrichten CTriggerEventsDlg
|
||
|
||
// MW 07/23/01: Added this because startpos=1+curev*3 isn´t anymore valid for calculating the next event
|
||
int GetEventParamStart(const CString& EventData, int param)
|
||
{
|
||
int count = atoi(GetParam(EventData, 0));
|
||
if (param >= count) {
|
||
return -1;
|
||
}
|
||
|
||
int pos = 1;
|
||
int i;
|
||
for (i = 0; i < param; i++) {
|
||
pos += 1; // jump to first eventtype param
|
||
int needs = atoi(GetParam(EventData, pos));
|
||
|
||
pos += 2; // jump to next usual eventtype
|
||
// if needs of last eventtype is 2, we need to add 1
|
||
if (needs == 2) {
|
||
pos += 1;
|
||
}
|
||
}
|
||
|
||
return pos;
|
||
}
|
||
|
||
void CTriggerEventsDlg::OnNewevent()
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
|
||
|
||
CIniFileSection& sec = ini.AddSection("Events");
|
||
|
||
int cval = atoi(GetParam(sec.GetString(m_currentTrigger), 0));
|
||
cval++;
|
||
char c[50];
|
||
itoa(cval, c, 10);
|
||
|
||
auto&& defParam = SetParam(sec[m_currentTrigger], 0, c) + ",0,0,0";
|
||
sec.SetString(m_currentTrigger, std::move(defParam));
|
||
|
||
|
||
UpdateDialog();
|
||
|
||
m_Event.SetCurSel(cval - 1);
|
||
OnSelchangeEvent();
|
||
}
|
||
|
||
int FindTokenX(CString data, char token, int n)
|
||
{
|
||
if (n <= 0) return -1;
|
||
|
||
int found = 0;
|
||
int pos = 0;
|
||
while (found < n) {
|
||
if (!pos)
|
||
pos = data.Find(token, 0);
|
||
else
|
||
pos = data.Find(token, pos + 1);
|
||
if (pos < 0) {
|
||
return -1;
|
||
}
|
||
|
||
found++;
|
||
}
|
||
|
||
return pos;
|
||
}
|
||
|
||
void CTriggerEventsDlg::OnDeleteevent()
|
||
{
|
||
char d[50];
|
||
//itoa(FindTokenX("0,1,2,3,4", ',', 3),d,10);
|
||
//MessageBox(d);
|
||
|
||
CIniFile& ini = Map->GetIniFile();
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
|
||
int sel2 = m_Event.GetCurSel();
|
||
if (sel2 < 0) {
|
||
return;
|
||
}
|
||
int curev = m_Event.GetItemData(sel2);
|
||
auto const title = TranslateStringACP("Delete event");
|
||
auto const content = TranslateStringACP("Do you really want to delete this event?");
|
||
if (MessageBox(content, title, MB_YESNO) == IDNO) {
|
||
return;
|
||
}
|
||
|
||
auto const& orig_data = ini["Events"][m_currentTrigger];
|
||
CString data = orig_data;
|
||
|
||
int v = atoi(GetParam(data, 0));
|
||
char c[50];
|
||
v--;
|
||
itoa(v, c, 10);
|
||
data = SetParam(data, 0, c);
|
||
|
||
int pos = GetEventParamStart(orig_data, curev);//1+curev*3;
|
||
//int posc=GetEventParamStart(orig_data, v);//1+v*3;
|
||
|
||
// MW 07/23/01:
|
||
// NEW DELETE EVENT CODE...
|
||
|
||
// Now check for those 2 param + code events...
|
||
BOOL bEvent1Needs4 = FALSE;
|
||
|
||
|
||
if (GetParam(data, pos + 1) == "2") {
|
||
bEvent1Needs4 = TRUE;
|
||
}
|
||
|
||
int count = 3;
|
||
if (bEvent1Needs4) {
|
||
count = 4;
|
||
}
|
||
|
||
int del_start = FindTokenX(data, ',', pos);
|
||
int del_end = FindTokenX(data, ',', pos + count);
|
||
if (del_end < 0) {
|
||
// beyond end, so delete all...
|
||
del_end = data.GetLength();
|
||
|
||
}
|
||
data.Delete(del_start, del_end - del_start);
|
||
|
||
/*
|
||
old delete event code, that used replacement. Not possible anymore because of 4 values/event sometimes now
|
||
|
||
int i;
|
||
for(i=0;i<3;i++)
|
||
data=SetParam(data,pos+i, GetParam(data,posc+i));
|
||
|
||
char* cupos=(char*)(LPCTSTR)data;
|
||
for(i=0;i<posc;i++)
|
||
{
|
||
cupos=strchr(cupos+1, ',');
|
||
if(i==posc-1)
|
||
{
|
||
cupos[0]=0;
|
||
break;
|
||
}
|
||
}*/
|
||
|
||
ini.SetString("Events", m_currentTrigger, data);
|
||
UpdateDialog();
|
||
|
||
}
|
||
|
||
void CTriggerEventsDlg::OnSelchangeEvent()
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
int selev = m_Event.GetCurSel();
|
||
if (selev < 0) {
|
||
return;
|
||
}
|
||
int curev = m_Event.GetItemData(selev);
|
||
|
||
|
||
int i;
|
||
|
||
auto const& EventData = ini["Events"][m_currentTrigger];
|
||
|
||
int startpos = GetEventParamStart(EventData, curev); //1+curev*3;
|
||
CString EventType = GetParam(EventData, startpos);
|
||
m_EventType.SetWindowText(EventType);
|
||
for (i = 0; i < m_EventType.GetCount(); i++) {
|
||
CString tmp;
|
||
m_EventType.GetLBText(i, tmp);
|
||
TruncSpace(tmp);
|
||
if (tmp == EventType) {
|
||
m_EventType.SetCurSel(i);
|
||
}
|
||
}
|
||
|
||
OnEditchangeEventtype();
|
||
}
|
||
|
||
void CTriggerEventsDlg::OnEditchangeEventtype()
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
int selev = m_Event.GetCurSel();
|
||
if (selev < 0) {
|
||
return;
|
||
}
|
||
int curev = m_Event.GetItemData(selev);
|
||
|
||
CString e1, e2;
|
||
while (m_Parameter.DeleteString(0) != CB_ERR);
|
||
|
||
|
||
CString eventtype, eventdata;
|
||
m_EventType.GetWindowText(eventtype);
|
||
TruncSpace(eventtype);
|
||
|
||
if (eventtype.GetLength() == 0) {
|
||
eventtype = "0";
|
||
m_EventType.SetWindowText(eventtype);
|
||
}
|
||
|
||
int pos = GetEventParamStart(ini["Events"][m_currentTrigger], curev); //1+3*curev;
|
||
|
||
BOOL bAlready4 = FALSE;
|
||
if (atoi(GetParam(ini["Events"][m_currentTrigger], pos + 1)) == 2) {
|
||
bAlready4 = TRUE;
|
||
}
|
||
|
||
ini.SetString("Events", m_currentTrigger, SetParam(ini["Events"][m_currentTrigger], pos, eventtype));
|
||
|
||
|
||
CString evsec = "Events";
|
||
#ifdef RA2_MODE
|
||
evsec = "EventsRA2";
|
||
#endif
|
||
|
||
|
||
if (!g_data[evsec].Exists(eventtype)) {
|
||
return;
|
||
}
|
||
eventdata = g_data[evsec][eventtype];
|
||
|
||
#ifdef RA2_MODE
|
||
auto const ra2EventConf = g_data.GetString("EventsRA2", eventtype);
|
||
if (!ra2EventConf.IsEmpty()) {
|
||
eventdata = ra2EventConf;
|
||
}
|
||
#endif
|
||
|
||
CString desc = GetParam(eventdata, 5);
|
||
desc.Replace("%1", ",");
|
||
m_EventDescription.SetWindowText(desc);
|
||
|
||
CString ptype[2];
|
||
ptype[0] = GetParam(eventdata, 1);
|
||
ptype[1] = GetParam(eventdata, 2);
|
||
|
||
|
||
int pListType[2];
|
||
pListType[0] = atoi(GetParam(g_data["ParamTypes"][ptype[0]], 1));
|
||
pListType[1] = atoi(GetParam(g_data["ParamTypes"][ptype[1]], 1));
|
||
|
||
int code = atoi(GetParam(g_data["ParamTypes"][ptype[0]], 2)); // usually 0
|
||
|
||
// **************************************
|
||
// MW ADD SUPPORT FOR 2 PARAMS+CODE
|
||
if (code == 2) {
|
||
// add code + event 0 ONLY IF THEY DO NOT ALREADY EXIST
|
||
if (!bAlready4) {
|
||
ini.SetString("Events", m_currentTrigger, SetParam(ini["Events"][m_currentTrigger], pos + 1, "2,0"));
|
||
}
|
||
} else {
|
||
// remove code + event 0
|
||
char c[50];
|
||
itoa(code, c, 10);
|
||
ini.SetString("Events", m_currentTrigger, SetParam(ini["Events"][m_currentTrigger], pos + 1, c));
|
||
|
||
if (bAlready4) {
|
||
CString data = ini["Events"][m_currentTrigger];
|
||
int del_start = FindTokenX(data, ',', pos + 2);
|
||
int del_end = FindTokenX(data, ',', pos + 3);
|
||
if (del_end < 0) {
|
||
// beyond end, so delete all...
|
||
del_end = data.GetLength();
|
||
|
||
}
|
||
data.Delete(del_start, del_end - del_start);
|
||
ini.SetString("Events", m_currentTrigger, data);
|
||
}
|
||
|
||
}
|
||
// **************************************
|
||
|
||
int i;
|
||
for (i = 0; i < 2; i++) {
|
||
int add = 0;
|
||
if (code == 2) {
|
||
add = 1;
|
||
}
|
||
if (atoi(ptype[i]) != 0 && atoi(ptype[i]) > 0 && atoi(ptype[i]) != 47) {
|
||
CString paramname = GetParam(g_data["ParamTypes"][ptype[i]], 0);
|
||
|
||
m_Parameter.SetItemData(m_Parameter.AddString(paramname), i + add);
|
||
}
|
||
}
|
||
|
||
m_ParamValue.SetWindowText("");
|
||
if (m_Parameter.GetCount() > 0) {
|
||
m_Parameter.SetCurSel(0);
|
||
OnSelchangeParameter();
|
||
}
|
||
|
||
|
||
auto triggerInfoCopy = ini["Triggers"][m_currentTrigger];
|
||
if (RepairTrigger(triggerInfoCopy)) {
|
||
ini.SetString("Triggers", m_currentTrigger, triggerInfoCopy);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void CTriggerEventsDlg::OnSelchangeParameter()
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
int selev = m_Event.GetCurSel();
|
||
if (selev < 0) {
|
||
return;
|
||
}
|
||
int curev = m_Event.GetItemData(selev);
|
||
|
||
int curselparam = m_Parameter.GetCurSel();
|
||
if (curselparam < 0) {
|
||
m_ParamValue.SetWindowText("");
|
||
return;
|
||
}
|
||
|
||
int curparam = m_Parameter.GetItemData(curselparam);
|
||
auto const EventData = ini["Events"][m_currentTrigger];
|
||
int startpos = GetEventParamStart(EventData, curev);//1+curev*3;
|
||
|
||
|
||
// MW FIX FOR CODE!=0
|
||
int original_cuparam = curparam;
|
||
#ifdef RA2_MODE
|
||
CString Param1 = GetParam(g_data["EventsRA2"][GetParam(EventData, startpos)], 1);
|
||
CString Code = GetParam(g_data["ParamTypes"][Param1], 2);
|
||
//MessageBox(Param1, Code);
|
||
if (atoi(Code) == 2) curparam--;
|
||
#endif
|
||
// END FIx
|
||
|
||
CString ParamType = GetParam(g_data["Events"][GetParam(EventData, startpos)], 1 + curparam);
|
||
#ifdef RA2_MODE
|
||
if (g_data["EventsRA2"].FindIndex(GetParam(EventData, startpos)) >= 0) {
|
||
ParamType = GetParam(g_data["EventsRA2"][GetParam(EventData, startpos)], 1 + curparam);
|
||
}
|
||
#endif
|
||
|
||
if (atoi(ParamType) < 0) {
|
||
return;
|
||
}
|
||
|
||
CString ListType = GetParam(g_data["ParamTypes"][ParamType], 1);
|
||
|
||
HandleParamList(m_ParamValue, atoi(ListType));
|
||
m_ParamValue.SetWindowText(GetParam(EventData, startpos + 1 + original_cuparam));
|
||
|
||
int i;
|
||
BOOL bFound = FALSE;
|
||
for (i = 0; i < m_ParamValue.GetCount(); i++) {
|
||
CString tmp;
|
||
m_ParamValue.GetLBText(i, tmp);
|
||
TruncSpace(tmp);
|
||
if (tmp == GetParam(EventData, startpos + 1 + original_cuparam)) {
|
||
m_ParamValue.SetCurSel(i);
|
||
bFound = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
/*if(!bFound)
|
||
{
|
||
// not found, change it...
|
||
|
||
if(m_ParamValue.GetCount()) {
|
||
m_ParamValue.SetCurSel(0);
|
||
OnEditchangeParamvalue();
|
||
}
|
||
else
|
||
{
|
||
// not numeric value?
|
||
|
||
CString p=GetParam(EventData,startpos+1+original_cuparam);
|
||
char c[50];
|
||
itoa(atoi(p), c, 10);
|
||
if(c!=p) {
|
||
m_ParamValue.SetWindowText("0");
|
||
OnEditchangeParamvalue();
|
||
}
|
||
}
|
||
}*/
|
||
}
|
||
|
||
void CTriggerEventsDlg::OnEditchangeParamvalue()
|
||
{
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
return;
|
||
}
|
||
int selev = m_Event.GetCurSel();
|
||
if (selev < 0) {
|
||
return;
|
||
}
|
||
int curev = m_Event.GetItemData(selev);
|
||
|
||
int curselparam = m_Parameter.GetCurSel();
|
||
if (curselparam < 0) {
|
||
m_ParamValue.SetWindowText("");
|
||
return;
|
||
}
|
||
|
||
int curparam = m_Parameter.GetItemData(curselparam);
|
||
|
||
auto const& eventData = ini["Events"][m_currentTrigger];
|
||
|
||
int startpos = GetEventParamStart(eventData, curev);// 1+curev*3;
|
||
|
||
|
||
CString newVal;
|
||
m_ParamValue.GetWindowText(newVal);
|
||
TruncSpace(newVal);
|
||
newVal.TrimLeft();
|
||
|
||
if (newVal.Find(",", 0) >= 0) {
|
||
newVal.SetAt(newVal.Find(",", 0), 0);
|
||
}
|
||
|
||
ini.SetString("Events", m_currentTrigger, SetParam(eventData, startpos + 1 + curparam, newVal));
|
||
}
|
||
|
||
void CTriggerEventsDlg::UpdateDialog()
|
||
{
|
||
// MW 07/20/01
|
||
Clear();
|
||
|
||
if (m_currentTrigger.GetLength() == 0) {
|
||
while (m_Event.DeleteString(0) != CB_ERR);
|
||
return;
|
||
}
|
||
CIniFile& ini = Map->GetIniFile();
|
||
|
||
while (m_EventType.DeleteString(0) != CB_ERR);
|
||
int i;
|
||
|
||
//9.3.2001: Only use specified section, do not merge
|
||
#ifndef RA2_MODE
|
||
CString sec = "Events";
|
||
#else
|
||
CString sec = "EventsRA2";
|
||
#endif
|
||
|
||
for (auto const& [eventid, eventdata] : g_data[sec]) {
|
||
//GetParam(*g_data.sections["Events"].GetValue(i),8);
|
||
/*#ifdef RA2_MODE
|
||
if(g_data.sections["EventsRA2"].FindIndex(eventid)>=0)
|
||
eventdata=g_data.sections["EventsRA2"].values[eventid];
|
||
#endif*/
|
||
|
||
CString text = eventid + " " + GetParam(eventdata, 0);
|
||
text.Replace("%1", ",");
|
||
#ifdef RA2_MODE
|
||
// MW 07/18/01
|
||
// for yuri mode, only check if it´s for RA2, else support it only if YR isnt´needed...
|
||
if (GetParam(eventdata, 7) == "1" && (yuri_mode || !atoi(GetParam(eventdata, 9)))) {
|
||
|
||
|
||
#else
|
||
if (GetParam(eventdata, 6) == "1") {
|
||
#endif
|
||
m_EventType.AddString(text);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
int cur_sel = m_Event.GetCurSel();
|
||
while (m_Event.DeleteString(0) != CB_ERR);
|
||
|
||
auto const& data = ini["Events"][m_currentTrigger];
|
||
int count = atoi(GetParam(data, 0));
|
||
|
||
for (i = 0; i < count; i++) {
|
||
char c[50];
|
||
itoa(i, c, 10);
|
||
|
||
CString s = TranslateStringACP("Event");
|
||
s += " ";
|
||
s += c;
|
||
|
||
m_Event.SetItemData(m_Event.AddString(s), i);
|
||
}
|
||
|
||
if (cur_sel < 0) {
|
||
cur_sel = 0;
|
||
}
|
||
if (cur_sel >= count) {
|
||
cur_sel = count - 1;
|
||
}
|
||
|
||
m_Event.SetCurSel(cur_sel);
|
||
|
||
|
||
OnSelchangeEvent();
|
||
}
|
||
|
||
// MW 07/20/01
|
||
void CTriggerEventsDlg::Clear()
|
||
{
|
||
m_EventType.SetWindowText("");
|
||
while (m_Parameter.DeleteString(0) != LB_ERR);
|
||
m_ParamValue.SetWindowText("");
|
||
m_EventDescription.SetWindowText("");
|
||
}
|