/* 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 . */ // AITriggerTypes.cpp: implementation file // #include "stdafx.h" #include "FinalSun.h" #include "AITriggerTypes.h" #include "Mapdata.h" #include "structs.h" #include "variables.h" #include "functions.h" #include "inlines.h" // AI trigger type enumeration enum AITriggerEnum { AIT_NONE = -1, AIT_ENEMY_OWNS_X_COND_N = 0, AIT_HOUSE_OWNS_X_COND_N, AIT_POWER_YELLOW, AIT_POWER_RED, AIT_ENEMY_MONEY_COND_N, AIT_CURTAIN_NEAR_READY, AIT_SPHERE_NEAR_READY, AIT_NEUTRAL_OWNS_X_COND_N, }; #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // property page CAITriggerTypes IMPLEMENT_DYNCREATE(CAITriggerTypes, CDialog) CAITriggerTypes::CAITriggerTypes() : CDialog(CAITriggerTypes::IDD) { //{{AFX_DATA_INIT(CAITriggerTypes) m_Flag3 = _T(""); m_Flag4 = _T(""); m_Name = _T(""); m_Flag6 = _T(""); m_Flag7 = _T(""); m_Flag8 = _T(""); m_Flag9 = _T(""); m_Enabled = FALSE; m_Condition = -1; m_Number = 0; m_Easy = FALSE; m_Medium = FALSE; m_Hard = FALSE; m_BaseDefense = FALSE; m_Skirmish = FALSE; m_Flag5 = _T(""); m_MultiSide = _T(""); //}}AFX_DATA_INIT } CAITriggerTypes::~CAITriggerTypes() { } void CAITriggerTypes::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAITriggerTypes) DDX_Control(pDX, IDC_TEAMTYPE1, m_TeamType1); DDX_Control(pDX, IDC_UNITTYPE, m_UnitType); DDX_Control(pDX, IDC_TEAMTYPE2, m_TeamType2); DDX_Control(pDX, IDC_FLAG2, m_Flag2); DDX_Control(pDX, IDC_FLAG1, m_Flag1); DDX_Control(pDX, IDC_DATA, m_Data); DDX_Control(pDX, IDC_OWNER, m_Owner); DDX_Control(pDX, IDC_FLOAT3, m_Float3); DDX_Control(pDX, IDC_FLOAT2, m_Float2); DDX_Control(pDX, IDC_FLOAT1, m_Float1); DDX_Control(pDX, IDC_AITRIGGERTYPE, m_AITriggerType); DDX_Text(pDX, IDC_FLAG4, m_Flag4); DDX_Text(pDX, IDC_NAME, m_Name); DDX_Check(pDX, IDC_ENABLED, m_Enabled); DDX_CBIndex(pDX, IDC_CONDITION, m_Condition); DDX_Text(pDX, IDC_NUMBER, m_Number); DDV_MinMaxInt(pDX, m_Number, 0, 256); DDX_Check(pDX, IDC_EASY, m_Easy); DDX_Check(pDX, IDC_MEDIUM, m_Medium); DDX_Check(pDX, IDC_HARD, m_Hard); DDX_Check(pDX, IDC_BASEDEFENSE, m_BaseDefense); DDX_Check(pDX, IDC_SKIRMISH, m_Skirmish); DDX_CBString(pDX, IDC_MULTISIDE, m_MultiSide); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAITriggerTypes, CDialog) //{{AFX_MSG_MAP(CAITriggerTypes) ON_CBN_SELCHANGE(IDC_AITRIGGERTYPE, OnSelchangeAitriggertype) ON_EN_CHANGE(IDC_NAME, OnChangeName) ON_CBN_EDITCHANGE(IDC_OWNER, OnEditchangeOwner) ON_CBN_EDITCHANGE(IDC_TEAMTYPE1, OnEditchangeTeamtype1) ON_CBN_EDITCHANGE(IDC_TEAMTYPE2, OnEditchangeTeamtype2) ON_CBN_EDITCHANGE(IDC_FLAG1, OnEditchangeFlag1) ON_CBN_EDITCHANGE(IDC_FLAG2, OnEditchangeFlag2) ON_CBN_EDITCHANGE(IDC_UNITTYPE, OnEditchangeUnittype) ON_CBN_EDITCHANGE(IDC_DATA, OnEditchangeData) ON_EN_CHANGE(IDC_FLOAT1, OnChangeFloat1) ON_EN_CHANGE(IDC_FLOAT2, OnChangeFloat2) ON_EN_CHANGE(IDC_FLOAT3, OnChangeFloat3) ON_EN_CHANGE(IDC_FLAG4, OnChangeFlag4) ON_BN_CLICKED(IDC_ENABLED, OnEnabled) ON_BN_CLICKED(IDC_ADD, OnAdd) ON_BN_CLICKED(IDC_DELETE, OnDelete) ON_CBN_EDITCHANGE(IDC_AITRIGGERTYPE, OnEditchangeAitriggertype) ON_CBN_SELCHANGE(IDC_CONDITION, OnSelchangeCondition) ON_EN_CHANGE(IDC_NUMBER, OnChangeNumber) ON_BN_CLICKED(IDC_EASY, OnEasy) ON_BN_CLICKED(IDC_MEDIUM, OnMedium) ON_BN_CLICKED(IDC_HARD, OnHard) ON_BN_CLICKED(IDC_BASEDEFENSE, OnBasedefense) ON_BN_CLICKED(IDC_SKIRMISH, OnSkirmish) ON_CBN_EDITCHANGE(IDC_MULTISIDE, OnEditchangeMultiside) ON_CBN_SELCHANGE(IDC_MULTISIDE, OnSelchangeMultiside) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // message handlers CAITriggerTypes void ListObjects(CComboBox& cb) { CComboBox& m_UnitType=cb; CIniFile& ini=Map->GetIniFile(); int i; CString ss="InfantryTypes"; for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } ss="VehicleTypes"; for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } ss="AircraftTypes"; for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } ss="BuildingTypes"; for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } for(i=0;iGetUnitName((char*)(LPCTSTR)type); s+=")"; m_UnitType.AddString(s); } } void CAITriggerTypes::UpdateDialog() { int sel=m_AITriggerType.GetCurSel(); m_AITriggerType.SetRedraw(FALSE); while(m_AITriggerType.DeleteString(0)!=CB_ERR); ListHouses(m_Owner,FALSE,TRUE); m_Owner.AddString(""); ListTeamTypes(m_TeamType1, TRUE); ListTeamTypes(m_TeamType2, TRUE); int i; for(i=0;iGetAITriggerTypeCount();i++) { AITRIGGERTYPE aitt; Map->GetAITriggerType(i, &aitt); CString s=aitt.ID; s+=" ("; s+=aitt.name; s+=")"; m_AITriggerType.AddString(s); } m_AITriggerType.SetCurSel(0); if(sel!=-1) m_AITriggerType.SetCurSel(sel); OnSelchangeAitriggertype(); m_AITriggerType.SetRedraw(TRUE); m_AITriggerType.RedrawWindow(); } void CAITriggerTypes::OnSelchangeAitriggertype() { int sel=m_AITriggerType.GetCurSel(); if(sel<0) return; CString aitrigger; m_AITriggerType.GetLBText(sel,aitrigger); TruncSpace(aitrigger); AITRIGGERTYPE aitt; Map->GetAITriggerType(Map->GetAITriggerTypeIndex(aitrigger), &aitt); m_Name=aitt.name; m_TeamType1.SetWindowText(aitt.teamtype1); m_Owner.SetWindowText(TranslateHouse(aitt.owner, TRUE)); m_Flag1.SetWindowText(aitt.techlevel); //m_Flag2.SetWindowText(aitt.type); int type=atoi(aitt.type)+1; m_Flag2.SetCurSel(type); m_UnitType.SetWindowText(aitt.unittype); m_Data.SetWindowText(aitt.data); m_Float1.SetWindowText(aitt.float1); m_Float2.SetWindowText(aitt.float2); m_Float3.SetWindowText(aitt.float3); //m_Flag3=aitt.skirmish; m_Skirmish=isTrue(aitt.skirmish); m_Flag4=aitt.flag4; //m_Flag5=aitt.multihouse; m_MultiSide=aitt.multihouse; m_BaseDefense=isTrue(aitt.basedefense); m_TeamType2.SetWindowText(aitt.teamtype2); m_Easy=isTrue(aitt.easy); m_Medium=isTrue(aitt.medium); m_Hard=isTrue(aitt.hard); m_Enabled=FALSE; CIniFile& ini=Map->GetIniFile(); if(ini.sections["AITriggerTypesEnable"].values.find((LPCTSTR)aitrigger)!=ini.sections["AITriggerTypesEnable"].values.end()) if(stricmp(ini.sections["AITriggerTypesEnable"].values[(LPCTSTR)aitrigger], "yes")==NULL) m_Enabled=TRUE; AITrigInfo info; info=ConvertToAITrigInfoFromHex((char*)(LPCSTR)aitt.data); m_Condition=info.Condition; m_Number=info.Number; ListObjects(m_UnitType); UpdateData(FALSE); } void CAITriggerTypes::OnChangeName() { UpdateData(); CString value; value=m_Name; if(value.GetLength()==0) value=" "; SetAITriggerParam(value, 0); UpdateDialog(); } void CAITriggerTypes::OnEditchangeOwner() { CString value; m_Owner.GetWindowText(value); value=TranslateHouse(value); SetAITriggerParam(value, 2); } void CAITriggerTypes::OnEditchangeTeamtype1() { CString value; m_TeamType1.GetWindowText(value); TruncSpace(value); SetAITriggerParam(value, 1); } void CAITriggerTypes::OnEditchangeTeamtype2() { CString value; m_TeamType2.GetWindowText(value); TruncSpace(value); SetAITriggerParam(value, 14); } void CAITriggerTypes::OnEditchangeFlag1() { CString value; m_Flag1.GetWindowText(value); SetAITriggerParam(value, 3); } void CAITriggerTypes::OnEditchangeFlag2() { CString value; m_Flag2.GetWindowText(value); TruncSpace(value); SetAITriggerParam(value, 4); } void CAITriggerTypes::OnEditchangeUnittype() { CString value; m_UnitType.GetWindowText(value); TruncSpace(value); SetAITriggerParam(value, 5); } void CAITriggerTypes::OnEditchangeData() { /* This function should also valid the data! */ CString value; m_Data.GetWindowText(value); TruncSpace(value); // max 64 chars... min 64 chars too... ((char*)(LPCTSTR)value)[64]=0; int ToInsert=64-value.GetLength(); CString nulls('0',ToInsert); value.Insert(value.GetLength()-ToInsert, nulls); SetAITriggerParam(value, 6); int editsel=m_Data.GetEditSel(); UpdateDialog(); m_Data.SetEditSel(editsel,editsel+1); } void CAITriggerTypes::OnChangeFloat1() { CString value; m_Float1.GetWindowText(value); SetAITriggerParam(value, 7); } void CAITriggerTypes::OnChangeFloat2() { CString value; m_Float2.GetWindowText(value); SetAITriggerParam(value, 8); } void CAITriggerTypes::OnChangeFloat3() { CString value; m_Float3.GetWindowText(value); SetAITriggerParam(value, 9); } void CAITriggerTypes::OnChangeFlag3() { } void CAITriggerTypes::OnChangeFlag4() { UpdateData(); CString value; value=m_Flag4; SetAITriggerParam(value, 11); } void CAITriggerTypes::OnChangeFlag5() { } void CAITriggerTypes::OnChangeFlag6() { } void CAITriggerTypes::OnChangeFlag7() { } void CAITriggerTypes::OnChangeFlag8() { UpdateData(); CString value; value=m_Flag8; SetAITriggerParam(value, 16); } void CAITriggerTypes::OnChangeFlag9() { UpdateData(); CString value; value=m_Flag9; SetAITriggerParam(value, 17); } void CAITriggerTypes::OnEnabled() { // enable or disable trigger UpdateData(); int sel=m_AITriggerType.GetCurSel(); if(sel<0) return; CString aitrigger; m_AITriggerType.GetLBText(sel,aitrigger); TruncSpace(aitrigger); CIniFile& ini=Map->GetIniFile(); if(m_Enabled) { // enable it ini.sections["AITriggerTypesEnable"].values[(LPCTSTR)aitrigger]="yes"; } else ini.sections["AITriggerTypesEnable"].values.erase((LPCTSTR)aitrigger); } void CAITriggerTypes::SetAITriggerParam(const char *value, int param) { int sel=m_AITriggerType.GetCurSel(); if(sel<0) return; CString aitrigger; m_AITriggerType.GetLBText(sel,aitrigger); TruncSpace(aitrigger); CIniFile& ini=Map->GetIniFile(); ini.sections["AITriggerTypes"].values[aitrigger]=SetParam(ini.sections["AITriggerTypes"].values[aitrigger],param,value); } void CAITriggerTypes::OnAdd() { CString ID=GetFreeID(); CIniFile& ini=Map->GetIniFile(); CString data="New AI Trigger,"; // now try to set a teamtype if(ini.sections["TeamTypes"].values.size()>0) { data+=*ini.sections["TeamTypes"].GetValue(0); } else { data+=""; } data+=",,"; // the flag here... i first thought it´s an ID, but it more seems to be an value specifying the importance of the trigger data+="1,"; // the flag 2 seems to be the type of the trigger. -1 seems to be pool data+="0,"; // now stuff data+=",0000000000000000000000000000000000000000000000000000000000000000,50.000000,30.000000,50.000000,1,0,1,1,"; // a pool seems to need both teamtypes the same if(ini.sections["TeamTypes"].values.size()>0) { data+="";//*ini.sections["TeamTypes"].GetValue(0); } else { data+=""; } data+=",1,1,1"; ini.sections["AITriggerTypes"].values[ID]=data; UpdateDialog(); // now make current id visible int i; for(i=0;iGetIniFile(); ini.sections["AITriggerTypes"].values.erase(aitrigger); ini.sections["AITriggerTypesEnable"].values.erase(aitrigger); UpdateDialog(); } void CAITriggerTypes::OnEditchangeAitriggertype() { OnSelchangeAitriggertype(); } AITrigInfo CAITriggerTypes::ConvertToAITrigInfoFromHex(char *aitinfo) { int index=0; AITrigInfo info; char* rawdata=(char*)&info; char hexbuff[3]="00"; char* dummy=NULL; while(*aitinfo!='\0') { while(isspace((int)*aitinfo)) aitinfo++; hexbuff[0]=*aitinfo++; ASSERT(*aitinfo!='\0'); if(*aitinfo!='\0'){ hexbuff[1]=*aitinfo++; } else { hexbuff[1]='\0'; } ASSERT(index=sizeof(AITrigInfo)) break; *rawdata++=strtol(hexbuff, &dummy, 16); index++; } return info; } char* CAITriggerTypes::ConvertToHexFromAITrigInfo(AITrigInfo info, char* buffer) { unsigned char* aitinfobuffer=(unsigned char*)buffer; /* ** Convert the AITrigInfo union data structure to ASCII format string */ { int index = 0; unsigned char *rawdata = (unsigned char *)&info; unsigned char *aitinfobuffptr = &aitinfobuffer[0]; for (; index < sizeof(AITrigInfo); index++, rawdata++, aitinfobuffptr += 2) { sprintf((char *)aitinfobuffptr, "%02x", *rawdata); } *aitinfobuffptr = '\0'; } return (char*)aitinfobuffer; } void CAITriggerTypes::OnSelchangeCondition() { int sel=m_AITriggerType.GetCurSel(); if(sel<0) return; UpdateData(TRUE); AITrigInfo info; info.Condition=(ConditionEnum)m_Condition; info.Number=m_Number; char buffer[65]; ConvertToHexFromAITrigInfo(info, buffer); SetAITriggerParam(buffer, 6); UpdateDialog(); } void CAITriggerTypes::OnChangeNumber() { int sel=m_AITriggerType.GetCurSel(); if(sel<0) return; UpdateData(TRUE); AITrigInfo info; memset(&info, 0, sizeof(AITrigInfo)); info.Condition=(ConditionEnum)m_Condition; info.Number=m_Number; char buffer[65]; ConvertToHexFromAITrigInfo(info, buffer); //MessageBox(buffer); //m_Data.SetWindowText(buffer); SetAITriggerParam(buffer, 6); UpdateDialog(); } void CAITriggerTypes::OnEasy() { UpdateData(); CString value; value="1"; if(!m_Easy) value="0"; SetAITriggerParam(value, 15); } void CAITriggerTypes::OnMedium() { UpdateData(); CString value; value="1"; if(!m_Medium) value="0"; SetAITriggerParam(value, 16); } void CAITriggerTypes::OnHard() { UpdateData(); CString value; value="1"; if(!m_Hard) value="0"; SetAITriggerParam(value, 17); } void CAITriggerTypes::OnBasedefense() { UpdateData(); CString value; value="1"; if(!m_BaseDefense) value="0"; SetAITriggerParam(value, 13); } void CAITriggerTypes::OnSkirmish() { UpdateData(); CString value; value="1"; if(!m_Skirmish) value="0"; SetAITriggerParam(value, 10); } void CAITriggerTypes::OnEditchangeMultiside() { UpdateData(); CString value; value=m_MultiSide; TruncSpace(value); SetAITriggerParam(value, 12); } void CAITriggerTypes::OnSelchangeMultiside() { CString s; CComboBox& box=*(CComboBox*)GetDlgItem(IDC_MULTISIDE); box.GetLBText(box.GetCurSel(), s); box.SetWindowText(s); OnEditchangeMultiside(); }