Antal1987
Warlord
Antal1987,
have you by chance looked into what makes the AI totally F-ck up using artillery ???
Not yet. AI functions are deeply undercovered. It's hard to recognize them.
Antal1987,
have you by chance looked into what makes the AI totally F-ck up using artillery ???
Maybe because... They are not really there?
Not yet. AI functions are deeply undercovered. It's hard to recognize them.
Would it be possible to increase the number of tradable units (only workers in the normal game) to more than 1 somehow? At the moment only the default capture unit is tradable with other civs.
Is there any way to make terrain buildings (mine, barricade, irrigation etc) culture/era specific?
Would it be possible to make units buildable only when a certain building is built like armies can only be built if a certain wonder is built first?
I think using multiple CPU is probably out since it may requires a lot of changes everywhere.
And for the limitation, it's not only a problem of RAM, but also how the format is coding some parts.
In theory, it should be possible to add a new era for instance. The save format just includes a number of ERA and the rest is dynamic.
Except if you change it in the savegame, it seems to be ignored when loading.
So maybe a first step is to check the "load" function and see what happens when loading such part: it is hardcoded? Or really dynamic?
Then you have a few other parts of the format which are more complicated. It's been years since I worked on that and I don't have all the references with me, but some parts are using for byte coding to reference items instead of a simple index.
This is harder to change
f_FileReadData(&v92, 4u, 1u, _File);
f_FileReadData(&Era_Count, 4u, 1u, _File);
if ( Era_Count != 4 )
{
f_Set_Script_Form_Num_Parameter(0, 4);
f_Process_Object_Name(0, &_BIC->field_1C[392] + 3, -1, -1);
f_Show_Error_Message("BIC_ERROR_ERAS");
}
class_BIC::Init_Eras(_BIC, 4);
v43 = 0;
if ( _BIC->ErasCount > 0 )
{
v44 = 0;
do
{
struct_Era_Type::ReadFromFile(&_BIC->Eras[v44], _File);
++v43;
++v44;
}
while ( v43 < _BIC->ErasCount );
}
v34 = BIC_Eras;
f_FileWriteData(&v34, 4u, 1u, _File);
v33 = _BIC->ErasCount;
f_FileWriteData(&v33, 4u, 1u, _File);
v17 = 0;
if ( _BIC->ErasCount > 0 )
{
v18 = 0;
do
{
struct_Era_Type::WriteToFile(&_BIC->Eras[v18], &_File->_ptr);
++v17;
++v18;
}
while ( v17 < _BIC->ErasCount );
}
if ( ControlID ) // Next Era
{
if ( ControlID != 1 )
return;
f_Play_Sound(12);
_EraID = _this->Current_EraID;
if ( _EraID != BIC_Data.ErasCount )
{
_New_EraID_1 = _EraID + 1;
_this->Current_EraID = _New_EraID_1;
if ( _New_EraID_1 )
{
CurrentString = 0;
v5 = Label_String_Pointers[198]; // Empty string
goto LABEL_11;
}
goto LABEL_27;
}
}
else // Prev Era
{
f_Play_Sound(12);
_EraID_2 = _this->Current_EraID;
if ( _EraID_2 )
{
_New_EraID_2 = _EraID_2 - 1;
_this->Current_EraID = _New_EraID_2;
CurrentString = 0;
v5 = Label_String_Pointers[198]; // Empty String
LABEL_11:
v8 = class_Labels_Collection::Get_Label(&Labels_Collection, v5);
...
v19 = &BIC_Data.Eras[_this->Current_EraID] - 264; // means &BIC_Data.Eras[_this->Current_EraID-1].Name
// ... copy v19 to CurrentString
class_Button::Set_Text(&_this->Prev_Era_Btn, &CurrentString);
_this->Prev_Era_Btn.vtable->m73_call_m22_Draw(&_this->Prev_Era_Btn);
}
LABEL_27:
if ( _this->Current_EraID < 3 )
{
// ...
v35 = &BIC_Data.Eras[_this->Current_EraID + 1].Name;
// ... copy v35 to CurrentString
class_Button::Set_Text(&_this->Next_Era_Btn, &CurrentString);
_this->Next_Era_Btn.vtable->m73_call_m22_Draw(&_this->Next_Era_Btn);
}
class_Advisor_Science_Form::f2(_this);
class_Base_Form::m73_call_m22_Draw(&Advisor_GUI.Base);
goto LABEL_45;
}
}
LABEL_45:
_this->vtable->Base.m73_call_m22_Draw(_this);
}
As for the image, it's just the "empty" boxes to use to draw the different tech, it's not linked to the number of eras.
void __thiscall class_Advisor_Science_Form::Draw_Advance(class_Advisor_Science_Form *this, int AdvanceID)
{
class_Advisor_Science_Form *_this; // ebp@1
struct_Advance_Layout *_Advance_Layouts; // ecx@1
struct_Advance_Layout *v4; // eax@1
int v5; // eax@2
int _EraID; // eax@12
int _Box_Group_Index; // esi@12
int v8; // ebx@12
int v9; // ecx@12
int v10; // eax@12
int v11; // ebx@15
int v12; // eax@15
int v13; // eax@16
int v14; // eax@18
int v15; // ecx@24
int v16; // ecx@24
class_PCX_Image *v17; // ecx@26
bool v18; // zf@30
int v19; // edx@33
int v20; // eax@33
struct_Advance_Layout *v21; // eax@39
char *v22; // edi@40
signed int v23; // ecx@40
signed int v24; // ecx@43
const void *v25; // esi@43
unsigned int v26; // edx@43
const CHAR *v27; // edi@43
signed int v28; // ecx@43
const CHAR *v29; // edi@46
signed int v30; // ecx@46
char *v31; // edi@50
signed int v32; // ecx@50
signed int v33; // ecx@53
const void *v34; // esi@53
unsigned int v35; // edx@53
const CHAR *v36; // edi@53
signed int v37; // ecx@53
int v38; // eax@58
const CHAR *v39; // edi@60
signed int v40; // ecx@60
signed int v41; // esi@60
char *v42; // edi@66
signed int v43; // ecx@66
signed int v44; // ecx@69
const void *v45; // esi@69
unsigned int v46; // edx@69
const CHAR *v47; // edi@69
signed int v48; // ecx@69
const CHAR *v49; // edi@72
signed int v50; // ecx@72
int v51; // eax@78
struct_Advance_Layout *v52; // eax@79
const CHAR *v53; // edi@81
signed int v54; // ecx@81
signed int v55; // ecx@84
const CHAR *v56; // edi@84
const CHAR *v57; // edi@87
signed int v58; // ecx@87
int v59; // eax@95
int v60; // eax@97
int v61; // ebp@98
int v62; // eax@100
int v63; // eax@106
char v64; // cl@107
char *v65; // edi@108
signed int v66; // ecx@108
signed int v67; // ecx@111
const void *v68; // esi@111
unsigned int v69; // edx@111
const CHAR *v70; // edi@111
signed int v71; // ecx@111
const CHAR *v72; // edi@115
signed int v73; // ecx@115
int v74; // [sp-18h] [bp-298h]@17
int v75; // [sp-18h] [bp-298h]@26
int v76; // [sp-18h] [bp-298h]@34
int v77; // [sp-14h] [bp-294h]@17
int v78; // [sp-14h] [bp-294h]@26
int v79; // [sp-14h] [bp-294h]@34
int v80; // [sp-10h] [bp-290h]@17
int v81; // [sp-10h] [bp-290h]@26
int v82; // [sp-10h] [bp-290h]@34
int v83; // [sp-Ch] [bp-28Ch]@16
int v84; // [sp-Ch] [bp-28Ch]@17
int v85; // [sp-Ch] [bp-28Ch]@26
int v86; // [sp-Ch] [bp-28Ch]@34
char v87; // [sp+Bh] [bp-275h]@1
int _Box_Type; // [sp+Ch] [bp-274h]@3
int Valuea; // [sp+Ch] [bp-274h]@63
int a4; // [sp+10h] [bp-270h]@12
int a5; // [sp+14h] [bp-26Ch]@12
int v92; // [sp+18h] [bp-268h]@12
int v93; // [sp+1Ch] [bp-264h]@12
int v94; // [sp+20h] [bp-260h]@12
int v95; // [sp+24h] [bp-25Ch]@8
unsigned int v96; // [sp+28h] [bp-258h]@1
int v97; // [sp+2Ch] [bp-254h]@12
char Dest; // [sp+30h] [bp-250h]@40
char Source; // [sp+80h] [bp-200h]@100
char v100[255]; // [sp+81h] [bp-1FFh]@100
char v101; // [sp+180h] [bp-100h]@103
char v102[255]; // [sp+181h] [bp-FFh]@103
_this = this;
v87 = 0;
_Advance_Layouts = this->Advance_Layouts;
v96 = 24 * AdvanceID;
v4 = &_Advance_Layouts[AdvanceID];
if ( LOBYTE(v4->field_0) )
return;
v5 = v4->field_4;
if ( v5 > 1 )
{
if ( v5 > 3 )
_Box_Type = (v5 == 4) + 2;
else
_Box_Type = 1;
}
else
{
_Box_Type = 0;
}
switch ( _Box_Type )
{
case 0:
v95 = 88;
break;
case 1:
v95 = 138;
break;
case 2:
v95 = 140;
break;
case 3:
v95 = 174;
break;
}
_EraID = _this->Current_EraID;
_Box_Group_Index = 16 * _Box_Type;
v8 = _this->Advance_Boxes_Images[16 * _Box_Type + _EraID].Height;
v97 = _this->Advance_Boxes_Images[16 * _Box_Type + _EraID].Width;
v94 = 116 * AdvanceID;
v9 = BIC_Data.Advances[AdvanceID].Y;
a4 = BIC_Data.Advances[AdvanceID].X;
v10 = _this->field_2764[16];
a5 = v9;
v92 = v97 + a4;
v93 = v8 + v9;
if ( v10 != -1 )
{
LOBYTE(v14) = class_Leader::Check_Advance_Available_To_Research(&Civilizations[v10], AdvanceID);
if ( !v14 || !class_Leader::Check_Advance(&Civilizations[_this->field_2764[17]], AdvanceID) )
{
v11 = &_this->Base_Data.Canvas;
v83 = 0;
goto LABEL_22;
}
LABEL_20:
v11 = &_this->Base_Data.Canvas;
class_Tile_Image_Info::Draw_Image2(
&_this->Advance_Boxes_Images[_Box_Group_Index] + _this->Current_EraID,
&_this->Base_Data.Canvas,
a4,
a5,
0);
v84 = 2;
v80 = 2;
v77 = -1;
v74 = _this->field_2764[14];
goto LABEL_24;
}
if ( class_Leader::Check_Advance(&Civilizations[_this->field_2764[17]], AdvanceID) )
goto LABEL_20;
if ( BYTE2(_this->Advance_Layouts[v96 / 0x18].field_0) )
{
v11 = &_this->Base_Data.Canvas;
class_Tile_Image_Info::Draw_Image2(
&_this->Advance_Boxes_Images[_Box_Group_Index + 4] + _this->Current_EraID,
&_this->Base_Data.Canvas,
a4,
a5,
0);
v12 = _this->field_2764[15];
LABEL_23:
v84 = 2;
v80 = 2;
v77 = -1;
v74 = v12;
goto LABEL_24;
}
LOBYTE(v13) = class_Leader::Check_Advance_Available_To_Research(&Civilizations[_this->field_2764[17]], AdvanceID);
v83 = 0;
v11 = &_this->Base_Data.Canvas;
if ( !v13 )
{
LABEL_22:
class_Tile_Image_Info::Draw_Image2(
&_this->Advance_Boxes_Images[_Box_Group_Index + 12] + _this->Current_EraID,
v11,
a4,
a5,
v83);
v12 = _this->field_2764[12];
goto LABEL_23;
}
class_Tile_Image_Info::Draw_Image2(
&_this->Advance_Boxes_Images[_Box_Group_Index + 8] + _this->Current_EraID,
&_this->Base_Data.Canvas,
a4,
a5,
0);
v84 = 2;
v80 = 2;
v77 = -1;
v74 = _this->field_2764[13];
LABEL_24:
class_PCX_Image::f9(v11, v74, v77, v80, v84);
sub_5A7C20(_this, AdvanceID, &a4);
v15 = *(&BIC_Data.Advances->Flags + v94);
v16 = v15 & 0x20000;
if ( v16 == 131072 && Civilizations[_this->field_2764[17]].Current_Research_ID == AdvanceID )
{
v85 = 0;
v81 = 0;
v78 = 0;
v75 = _this->field_2764[3];
v17 = v11;
LABEL_27:
class_PCX_Image::f6(v17, v75, v78, v81, v85);
switch ( _Box_Type )
{
case 0:
class_Tile_Image_Info::Draw_Image2(_this->Icon_Required_Images, v11, a4 + 88, a5, 0);
v19 = a5;
v20 = a4 + 88;
goto LABEL_37;
case 1:
class_Tile_Image_Info::Draw_Image2(_this->Icon_Required_Images, v11, a4 + 145, a5 - 4, 0);
v86 = 0;
v82 = BIC_Data.field_3E3C;
v79 = a5 - 4;
v76 = a4 + 145;
break;
case 2:
class_Tile_Image_Info::Draw_Image2(_this->Icon_Required_Images, v11, a4 + 145, a5 - 4, 0);
v86 = 0;
v82 = BIC_Data.field_3E3C;
v79 = a5 - 4;
v76 = a4 + 145;
break;
case 3:
class_Tile_Image_Info::Draw_Image2(_this->Icon_Required_Images, v11, a4 + 172, a5 - 4, 0);
v19 = a5 - 4;
v20 = a4 + 172;
LABEL_37:
v86 = 0;
v82 = BIC_Data.field_3E3C;
v79 = v19;
v76 = v20;
break;
}
sub_5F8760(&_this->Icon_Required_Images[1], v11, v76, v79, v82, v86);
goto LABEL_39;
}
v85 = 0;
v81 = 0;
v78 = 0;
if ( Civilizations[_this->field_2764[17]].Current_Research_ID == AdvanceID )
{
class_PCX_Image::f6(v11, _this->field_2764[2], 0, 0, 0);
}
else
{
v18 = v16 == 131072;
v17 = v11;
if ( v18 )
{
v75 = _this->field_2764[4];
goto LABEL_27;
}
class_PCX_Image::f6(v11, _this->field_2764[5], 0, 0, 0);
}
LABEL_39:
CurrentString = 0;
v21 = &_this->Advance_Layouts[v96 / 0x18];
if ( BYTE2(v21->field_0) )
{
_itoa(v21->field_8, &Dest, 10);
v22 = &Dest;
v23 = -1;
do
{
if ( !v23 )
break;
v18 = *v22++ == 0;
--v23;
}
while ( !v18 );
v24 = ~v23;
v25 = &v22[-v24];
v26 = v24;
v27 = &CurrentString;
v28 = -1;
do
{
if ( !v28 )
break;
v18 = *v27++ == 0;
--v28;
}
while ( !v18 );
memcpy((v27 - 1), v25, v26);
v29 = &CurrentString;
v30 = -1;
do
{
if ( !v30 )
break;
v18 = *v29++ == 0;
--v30;
}
while ( !v18 );
*(v29 - 1) = *".";
}
v31 = &BIC_Data.Advances->Name[v94];
v32 = -1;
do
{
if ( !v32 )
break;
v18 = *v31++ == 0;
--v32;
}
while ( !v18 );
v33 = ~v32;
v34 = &v31[-v33];
v35 = v33;
v36 = &CurrentString;
v37 = -1;
do
{
if ( !v37 )
break;
v18 = *v36++ == 0;
--v37;
}
while ( !v18 );
memcpy((v36 - 1), v34, v35);
if ( !f_Is_Net_Game() )
{
if ( f_Is_Net_Game() )
{
v38 = Render_Flags;
LOBYTE(v38) = Render_Flags & 0xF3;
Render_Flags = v38;
}
if ( (Render_Flags & 4) == 4 )
{
v39 = &CurrentString;
v40 = -1;
v41 = &Civilizations[1];
do
{
if ( !v40 )
break;
v18 = *v39++ == 0;
--v40;
}
while ( !v18 );
Valuea = 1;
*(v39 - 1) = *" ";
v94 = &Civilizations[1];
do
{
if ( Global_Civ_Flags1 & (1 << *(v41 + 28)) && class_Leader::Check_Advance(v41, AdvanceID) )
{
_itoa(Valuea, &Dest, 10);
v42 = &Dest;
v43 = -1;
do
{
if ( !v43 )
break;
v18 = *v42++ == 0;
--v43;
}
while ( !v18 );
v44 = ~v43;
v45 = &v42[-v44];
v46 = v44;
v47 = &CurrentString;
v48 = -1;
do
{
if ( !v48 )
break;
v18 = *v47++ == 0;
--v48;
}
while ( !v18 );
memcpy((v47 - 1), v45, v46);
v49 = &CurrentString;
v50 = -1;
do
{
if ( !v50 )
break;
v18 = *v49++ == 0;
--v50;
}
while ( !v18 );
v41 = v94;
*(v49 - 1) = word_6850CC;
}
v41 += 8420;
++Valuea;
v94 = v41;
}
while ( v41 < &Civilizations_End );
}
}
if ( _this->field_2764[16] == -1 )
{
LOBYTE(v51) = class_Leader::Check_Advance_Available_To_Research(
(8420 * _this->field_2764[17] + 10825304),
AdvanceID);
if ( v51 )
{
v52 = &_this->Advance_Layouts[v96 / 0x18];
if ( !BYTE2(v52->field_0) || v52->field_8 == 1 )
{
v53 = &CurrentString;
v54 = -1;
do
{
if ( !v54 )
break;
v18 = *v53++ == 0;
--v54;
}
while ( !v18 );
v55 = -1;
*(v53 - 1) = *" ";
v56 = &CurrentString;
do
{
if ( !v55 )
break;
v18 = *v56++ == 0;
--v55;
}
while ( !v18 );
*(v56 - 1) = *"(";
class_Leader::Get_Advance_Research_Time_String(
(8420 * _this->field_2764[17] + 10825304),
&CurrentString,
AdvanceID,
1);
v57 = &CurrentString;
v58 = -1;
do
{
if ( !v58 )
break;
v18 = *v57++ == 0;
--v58;
}
while ( !v18 );
*(v57 - 1) = *")";
}
}
}
if ( BYTE1(_this->Advance_Layouts[v96 / 0x18].field_0) )
class_PCX_Image::f9(v11, _this->field_2764[8], -1, 2, 2);
if ( f_Is_Net_Game() )
goto LABEL_122;
if ( f_Is_Net_Game() )
{
v59 = Render_Flags;
LOBYTE(v59) = Render_Flags & 0xF3;
Render_Flags = v59;
}
if ( (Render_Flags & 4) != 4 )
{
LABEL_122:
v60 = class_PCX_Image::Get_String_Width2(v11, &CurrentString);
if ( v60 + 10 > v95 )
{
v61 = 0;
while ( strlen(&CurrentString) >= v61 + 1 )
{
Source = 0;
strncpy(&Source, &CurrentString, v61 + 1);
v100[v61] = 0;
v62 = class_PCX_Image::Get_String_Width2(v11, &Source);
if ( v62 + 10 <= v95 )
{
if ( !v87 )
{
v101 = 0;
strncpy(&v101, &Source, v61 + 1);
v102[v61] = 0;
}
}
else
{
v87 = 1;
}
++v61;
if ( v87 )
goto LABEL_108;
}
v63 = 0;
do
{
v64 = *(&CurrentString + v63);
*(&v101 + v63++) = v64;
}
while ( v64 );
LABEL_108:
v65 = &v101;
v66 = -1;
CurrentString = 0;
do
{
if ( !v66 )
break;
v18 = *v65++ == 0;
--v66;
}
while ( !v18 );
v67 = ~v66;
v68 = &v65[-v67];
v69 = v67;
v70 = &CurrentString;
v71 = -1;
do
{
if ( !v71 )
break;
v18 = *v70++ == 0;
--v71;
}
while ( !v18 );
memcpy((v70 - 1), v68, v69);
if ( v87 )
{
v72 = &CurrentString;
v73 = -1;
do
{
if ( !v73 )
break;
v18 = *v72++ == 0;
--v73;
}
while ( !v18 );
*(v72 - 1) = *dword_684EEC;
}
}
}
class_PCX_Image::Draw_String(v11, &CurrentString, a4 + 15, a5 + 18, strlen(&CurrentString));
}
What is linked is the image used as a background for techs (the images with arrows going from tech to tech).
So, it seems they actually disabled reading if here is more than 4 eras when loading. But since Init_Eras seems to be using 4 as a parameters, and then the test is based on ErasCount, there is hope that it can work with more than 4 eras!