boformer / BuildingThemes

Mod for Cities:Skylines
http://steamcommunity.com/sharedfiles/filedetails/?id=466158459
MIT License
13 stars 11 forks source link

Possible 'No High Rises' policy overriding? #14

Open bloodypenguin opened 9 years ago

bloodypenguin commented 9 years ago

Vanilla 'No High Rises' policy just bans Level 5 Res. (and Level3 Office and Commercial) buildings. But there are lots of custom high rise assets that are Level1-4 (especially rtrstream's) and not so tall assets of Level 5 which makes that policy impractical. Is it possible to actually measure asset's height and filter buildings by it in GetRandomBuildingInfo method and at the same time allowing growing of Level 5 buildings in 'Ho High Rises' districts?

boformer commented 9 years ago

I only know that the policies are hidden deep in the source code (was going after it when I created the GUI).

It would definitely be possible to ban more buildings if the building height can be obtained (by filtering the list).

boformer commented 9 years ago

I inspected the source code of the game to see how we can override the policy.

public override void ResidentialBuildingAI.SimulationStep:

// seems like this code demolishes level5 buildings in highriseban districts
if (this.m_info.m_class.m_subService == ItemClass.SubService.ResidentialHigh && (cityPlanningPolicies & DistrictPolicies.CityPlanning.HighriseBan) != DistrictPolicies.CityPlanning.None && this.m_info.m_class.m_level == ItemClass.Level.Level5)
{
    SimulationManager instance2 = Singleton<SimulationManager>.instance;
    if (instance2.m_randomizer.Int32(10u) == 0 && Singleton<ZoneManager>.instance.m_lastBuildIndex == instance2.m_currentBuildIndex)
    {
        District[] expr_179_cp_0 = instance.m_districts.m_buffer;
        byte expr_179_cp_1 = district;
        expr_179_cp_0[(int)expr_179_cp_1].m_cityPlanningPoliciesEffect = (expr_179_cp_0[(int)expr_179_cp_1].m_cityPlanningPoliciesEffect | DistrictPolicies.CityPlanning.HighriseBan);
        buildingData.m_flags |= Building.Flags.Demolishing; 
        instance2.m_currentBuildIndex += 1u;
    }
}

private void ResidentialBuildingAI.CheckBuildingLevel:

// "level3" is the calculated level that the building should upgrade to
if (level3 > this.m_info.m_class.m_level)
{
    num3 = 0;
    num5 = 0;

    // this piece of code checks if the policy is enabled
    if (this.m_info.m_class.m_subService == ItemClass.SubService.ResidentialHigh && (cityPlanningPolicies & DistrictPolicies.CityPlanning.HighriseBan) != DistrictPolicies.CityPlanning.None && level3 == ItemClass.Level.Level5)
    {
        District[] expr_414_cp_0 = instance.m_districts.m_buffer;
        byte expr_414_cp_1 = district;
        expr_414_cp_0[(int)expr_414_cp_1].m_cityPlanningPoliciesEffect = (expr_414_cp_0[(int)expr_414_cp_1].m_cityPlanningPoliciesEffect | DistrictPolicies.CityPlanning.HighriseBan);
        // here the level is reduced to 4 if the policy is enabled
        level3 = ItemClass.Level.Level4; 
        num3 = 1;
    }
    // if the upgrade level is still higher than the current level, start upgrading
    if (buildingData.m_problems == Notification.Problem.None && level3 > this.m_info.m_class.m_level && this.GetUpgradeInfo(buildingID, ref buildingData) != null)
    {
        frameData.m_constructState = 0;
        base.StartUpgrading(buildingID, ref buildingData);
    }
}

Similar code can be found in the commercial and office AIs. We could detour the sealed methods and extend the AIs to override the virtual methods to change the behavior of the policy.

bloodypenguin commented 9 years ago

Each mesh has bounds.size property:

boformer commented 9 years ago

:+1:

bloodypenguin commented 9 years ago

Nohealforu's Building Simulation Overhaul overrides No High Rises policy in the suggested way. But it completely replaces buildings AI, which renders it incompatible with our mod. We may use its height calculation algorithm though :) We definitely need to find a way to detour virtual functions.