View Single Post
pan0s
Senior Member
Join Date: Nov 2017
Old 07-24-2021 , 06:04   Re: [L4D2] Random / Next Map [v1.1 | 8 May 2021]
Reply With Quote #7

Quote:
Originally Posted by Deadpool69 View Post
I tried to add my own custom maps to the .sp file, but when I compiled it, the maps wouldn't load even though I added their names to the translation file.

Here's the list of my edited .sp file, and also my .cfg file. I only edited the maps section of the .sp file, nothing else.

.SP
Code:
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
#include <pan0s>

#define CVAR_FLAGS			FCVAR_NOTIFY
#define VERSION             "v1.1"

enum
{
    MAP_PREV,
    MAP_NEXT,
}

// Official map codes list
char g_sMaps[][][] =
{
    //prev, next
	//{"c1m1_hotel","c8m1_apartment",},
	//{"c2m1_highway","c9m1_alleys",},
	//{"c3m1_plankcountry","c10m1_caves",},
	//{"c4m1_milltown_a","c11m1_greenhouse",},
	//{"c5m1_waterfront","c12m1_hilltop",},
	//{"c6m1_riverbank","c13m1_alpinecreek",},
	//{"c7m1_docks","c14m1_junkyard",},
	
	//Best classical maps	
	{"l4d2_stadium1_apartment","l4d2_ff01_woods",},
	{"l4d2_daybreak01_hotel","l4d_deathaboard01_prison",},
	{"beldurra2_1","saltwell_1_d",},
	{"wth_1","uz_crash",},
	{"de01_sewersde2","ec01_outlets",},
	{"l4d_ihm01_forest","dm1_suburbs",},
	{"redemptionII-deadstop","hotel01_market_two",},
	{"l4d2_scream01_yards","highway01_apt_20130613",},
	{"l4d_149_1","cdta_01detour",},
	{"AirCrash","esc_jailbreak",},
	{"m1_beach","lc_museum_hall25",},
	{"the_return_lvl1","l4d_thewoods2_21",},
	{"l4d_military_history_house","l4d_MIC2_TrapmentD",},
	{"l4d2_motamap_m1","l4d2_deadcity01_riverside",},
	{"desperate_houseway","Dead_Series1",},
	{"l4d2_ic_1_city","l4d2_ic_2_1",},
	{"l4d_damit01_orchard","damitdc1",},
	{"uf1_boulevard","unsdwn_mp_1",},
	{"bhm1_outskirts","x1m1_cliffs",},
	{"l4d2_tgtn01_fridayroad","BadHoodL1",},
	{"l4d2_downtowndine01","cwm1_intro",},
	{"l4dblackoutbasement1","grmap1",},
	{"lost01_club","l4d_dbde_citylights",},

	//Best newer maps    //{"appartments","c2m1_undark","c3m1_rurallighthouse","l4d2_roadtonowhere_route01","l4d2_morgan_road","p84m1_apartment","bjrtcre_m1","mayuns_1","hpmap1","otosotr_m1","bt1","RichardsWorking_Map","hiking_trails","rw_beach1","l4d_greyscale_01_street","ddntr1_01urban","l4d2_deathwoods01_stranded","l4d_deadgetaway01_dam","ds2_1","shopcenter","dw_woods","l4d2_kmaps_ravine","deadbeat01_forest","claustrophobia1","l4d_coldfear01_smallforest","l4d_coaldBlood01","2ee_01","l4d_cardiff",},

	// Average maps	//{"l4d2_draxmap1","l4d_draxmap0","wildride01","tripday_m1","TheCure001","bjrtc2_lvl1","rh_map01","l4d2_deadflagblues01_city","l4d2_feetunder_outpostazbo","l4d_priston01","1BM","l4d2-DisposalFacility","l4d2_base_east","Underground3","pt_home1","l4d2_planb1_v051","fox_river","nt01_mansion","l4d_auburn","d1c1","gr-mapone-7","outline_m1","l4d_lastnight01_arrival","dead_death_02","l4d_cuirmeat01","alleys1","getout","The Apartments","Return_Home","versus_1","l4d2_fallindeath01","l4d2_eft1_subsystem","l4d2_diescraper1_apartment_36","01_Derailed","canyondownthedrain","l4d2_camp_dead","l4d2_tunnel","l4d_deathrow01_streetstlm","l4d_redsea01_roofs","l4d_bureaux","route_to_city_vs1","apartment","patientscab","l4d2_darkblood01_tanker","lst_l4dmap_a","l4d_co_canal","cotd01_apartments","l4d_ccritical01csd","bloodtracks_01","bdp_bunker01","Las","youcallthatalanding","carnage_jail",},
	
	//A series of maps
	//{"beginninghours_m1_shipv2","Frozen_m1_streets","neverendingwar_train","kickedout_m1_subway","lasthours_m1_alleys","revenge_m1_office_new",},
	
	// Maps with lots of water
	{"c1m1_outerbayous_a","death_sentence_1",},
	{"dayofthedead1","NewRise",},
	{"redtide_01_alleyways","riptide_map1_final",},
	
	//Mashups
	//{"amsterdam1etd","citystreets1ewc","Hideout01_v5etd","soi_m1_metrostation","l4d2_route66",},
	
	// Short maps	//{"m1_village","the_tunnels","building","gasfever_1","ddg1_tower_v2_1","tlv01_city","l4d_suburb01_school","l4d2_sbtd_01","campanar_coop_vs","l4d_noe1","l4d_sc_market","cbm1_lake","l4d_hopedb_gorge01","l4d_5tolife01",},

	// Halloween maps
	//{"castle_map_01","l4d_tbm_1","hf01_theforest","grave_yard",},
	
	// Christmas Maps
	//{"c30m1","wow_map1","l4d_zero01_south","azhill1","Signal_Broken",},
	
	// Asian maps
	{"l4d_yama_1","1_m1",},
	{"beta_thecity1","msd1_town",},
	{"l4c2_wall","ch_map1_city",},
	{"port_01","l4d2_wanli01",},
	{"bp_mapalpha1","WaterCity",},

	// Latin/Euro maps
	{"bsas_m1_barrios","srocchurch",},
	{"l4d_viennacalling2_1","eu01_residential_b16",},
	{"venissia","m1_fabbrecce",},

	// Half-Life maps
	{"l4d2_trainstation_01","l4d2_canals_01",},
	{"l4d2_canals_07","l4d_ravenholm01_blackmesa",},
	{"l4d2_ravenholmwar_1","backtoravenholm_v4_01",},
	{"l4d2_coast_01","l4d2_city17_01",},
	{"wfp1_track","omf_01",},
	
	// Modded official maps
	//{"dcr_m1_hotel","dkr_m1_motel",},
	//{"dprm1_milltown_a","c5m1_darkwaterfront",},
	//{"c8m1_apartment_daytime","l4d2_hospital01_apartment",},
	//{"ft_m1_apartments","Ulice","l4d_reverse_hos01_rooftop",},
	//{"c9m1_alleys_daytime","l4d2_garage01_alleys_a","Alejki",},
	//{"l4d2_smalltownday01_caves","l4d2_smalltown01_caves",},
	//{"l4d2_DeathToll01_clam","Tunel",},
	//{"c11m1_greenhouse_day","l4d2_airport01_greenhouse",},
	//{"l4d_farm01_hilltop_day","l4d2_farm01_hilltop","l4d_farm05_cornfield_revbh",},
	//{"csm1_beta_alpinecreek","c14m1_day_junkyard",},
	//{"phantasmagoria01","r_concert",},
};      

// ConVar
ConVar cvar_random_on;
ConVar cvar_delay;
ConVar cvar_random_official_on;
ConVar cvar_random_custom_on;
ConVar cvar_random_repeat_num;

ArrayList g_listMap;

int g_iStart;
int g_iEnd;
int g_iMapSize;
public Plugin myinfo =
{
	name = "L4D2 Next Map",
	description = "When the end of finale chapter, map will be changed automatically.",
	author = "pan0s",
	version = "1.1",
	url = ""
};

public void OnPluginStart()
{
    LoadTranslations("l4d2_nextmap.phrases");
    
    RegAdminCmd("sm_rm", HandleCmdRm, ADMFLAG_KICK);
    RegAdminCmd("sm_nm", HandleCmdNm, ADMFLAG_KICK);

    CreateConVar("l4d2_maps_version", VERSION, "L4D2 auto change next map version", CVAR_FLAGS);
    cvar_delay = CreateConVar("l4d2_maps_delay", "5.0", "How many seconds does it wait for the changing map after finale win?", CVAR_FLAGS, true, 0.0);

    cvar_random_on = CreateConVar("l4d2_maps_random_on", "1", "Next map is random?\n0=Off, 1=On", CVAR_FLAGS, true, 0.0, true, 1.0);
    cvar_random_official_on = CreateConVar("14d2_random_official_on", "1", "Random map including official maps?\n0=Off, 1=On", CVAR_FLAGS, true, 0.0, true, 1.0);
    cvar_random_custom_on = CreateConVar("l4d2_random_custom_on", "1", "Random map including custom maps?\n0=Off, 1=On", CVAR_FLAGS, true, 0.0, true, 1.0);
    cvar_random_repeat_num = CreateConVar("l4d2_custom_random_repeat_num", "0", "How many random maps changed, then allow repeating changed maps?\n0=Never until all map changed once", CVAR_FLAGS, true, 0.0);


    HookEvent("finale_win", Event_FinaleWin);

    AutoExecConfig(true, "l4d2_nextmap");

    g_listMap = new ArrayList();

    g_iStart = 0;
    if(!cvar_random_official_on.BoolValue && sizeof(g_sMaps)>14) g_iEnd = 14;
    g_iEnd = sizeof(g_sMaps) -1;
    if(!cvar_random_custom_on.BoolValue) g_iEnd = 13;
    g_iMapSize = (g_iEnd + 1 - g_iStart);
}

public void OnMapStart()
{
    char map[32];
    GetCurrentMap(map, sizeof(map));
    int mapId = FindMapId(map, MAP_NEXT);

    // push current map to map list
    if(mapId != -1)
    {
        int repeatNum = cvar_random_repeat_num.IntValue;
        if(g_listMap.Length +1 >= g_iMapSize || repeatNum > 0 && g_listMap.Length +1 >=repeatNum) g_listMap.Clear();
        g_listMap.Push(mapId);
        // PrintToServer("================MAP: %d, SIZE:%d================", mapId, g_listMap.Length);
    }
}

public int FilterRandMap()
{
    int next = GetRandomInt(g_iStart, g_iEnd);

    bool isSucceed;
    while(g_listMap.Length > 0)
    {
        for(int i = 0; i < g_listMap.Length; i++)
        {
            int map = g_listMap.Get(i);
            if(map == next)
            {
                next = GetRandomInt(g_iStart, g_iEnd);
                break;
            }
            if(i == g_listMap.Length-1) isSucceed = true;
        }
        if(isSucceed) return next;
    }
    return next;
}

public void GetRandMap(char[] buffer)
{
    // CPrintToChatAll("%d/%d, L:%d, mapsize:%d", g_iStart, g_iEnd, g_listMap.Length, g_iMapSize);
    int next = FilterRandMap();
    Format(buffer, 32, "%s", g_sMaps[next][1]);
}

public int FindMapId(const char[] map, const int type)
{
    int x = 0;

    for(int i=0; i<sizeof(g_sMaps); i++)
    {
        x = i;
        if(StrEqual(map, g_sMaps[i][type])) break;
        if(x == sizeof(g_sMaps) - 1) x = -1; // Next map not found
    }
    return x;
}

public void GetNextMapEx(char[] buffer, bool isForceRand)
{
    if(isForceRand || cvar_random_on.BoolValue) GetRandMap(buffer);
    else
    {
        char map[32];
        GetCurrentMap(map, sizeof(map));
        int mapId = FindMapId(map, MAP_PREV);
        
        if(mapId == -1)
        {
            GetRandMap(buffer);
            return;
        }
        Format(buffer, 32, "%s", g_sMaps[mapId][1]);
    }
}

void Next(bool isForceRand = false)
{
    char map[32];
    GetNextMapEx(map, isForceRand);
    float delay = cvar_delay.FloatValue;

    for(int i=1; i<= MaxClients; i++)
    {
        if(!IsValidClient(i)) continue;

        char translated[64];
        if(TranslationPhraseExists(map)) Format(translated, sizeof(translated), "%T", map, i);
        else Format(translated, sizeof(translated), "%s", map, i);
        CPrintToChat(i, "%T%T", "SYSTEM", i, "COMPLETED_FINALE", i, translated, delay);
    }

    DataPack pack = CreateDataPack();
    pack.WriteString(map);
    CreateTimer(delay, HandleTimerNextMap, pack);
}

public Action Event_FinaleWin(Event event, char[] name, bool dontBroadcast)
{
    Next();
}

public Action HandleCmdRm(int client, int args)
{
	Next(true);
}

public Action HandleCmdNm(int client, int args)
{
	Next();
}

public Action HandleTimerNextMap(Handle timer, DataPack pack)
{
    pack.Reset();
    char map[32];
    pack.ReadString(map, sizeof(map));
    ServerCommand("changelevel %s", map);
    delete pack;
}
.CFG
Code:
// This file was auto-generated by SourceMod (v1.10.0.6499)
// ConVars for plugin "l4d2_nextmap.smx"


// Random map including official maps?
// 0=Off, 1=On
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
14d2_random_official_on "1"

// How many random maps changed, then allow repeating changed maps?
// 0=Never until all map changed once
// -
// Default: "0"
// Minimum: "0.000000"
l4d2_custom_random_repeat_num "0"

// How many seconds does it wait for the changing map after finale win?
// -
// Default: "5.0"
// Minimum: "0.000000"
l4d2_maps_delay "2.5"

// Next map is random?
// 0=Off, 1=On
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2_maps_random_on "1"

// L4D2 auto change next map version
// -
// Default: "v1.1"
l4d2_maps_version "v1.1"

// Random map including custom maps?
// 0=Off, 1=On
// -
// Default: "1"
// Minimum: "0.000000"
// Maximum: "1.000000"
l4d2_random_custom_on "1"
You have to use the last chapter map code for the previous map,
e.g. c1m4_atrium

else, it can't be detected which is the last chapter.
pan0s is offline