diff --git a/README.md b/README.md index beb0c3e..939e709 100644 --- a/README.md +++ b/README.md @@ -101,4 +101,4 @@ Technically it is louis using minigun with a model change, but it works fine. Note: Sometimes bill model fails to spawn in, and is just invisible. * **Commands:** - * `sm_spawn_minigun_bot ` - Spawns the ai bot infront of wherever you are looking. Can also use numbers (0-7). \ No newline at end of file + * `sm_spawn_minigun_bot ` - Spawns the ai bot infront of wherever you are looking. Can also use numbers (0-7). \ No newline at end of file diff --git a/plugins/csgo-misc.smx b/plugins/csgo-misc.smx new file mode 100644 index 0000000..fff0de8 Binary files /dev/null and b/plugins/csgo-misc.smx differ diff --git a/plugins/l4d2_ai_minigun.smx b/plugins/l4d2_ai_minigun.smx index 5c862a1..a3747f0 100644 Binary files a/plugins/l4d2_ai_minigun.smx and b/plugins/l4d2_ai_minigun.smx differ diff --git a/scripting/include/jutils.inc b/scripting/include/jutils.inc index b1a7bc2..b3dba4f 100644 --- a/scripting/include/jutils.inc +++ b/scripting/include/jutils.inc @@ -62,11 +62,11 @@ stock bool FindSurvivorModel(const char str[16], char[] model, int modelStrSize) switch(possibleNumber) { case 0: { strcopy(model, modelStrSize, MODEL_NICK); - } case 1: { + } case 3: { strcopy(model, modelStrSize, MODEL_ELLIS); } case 2: { strcopy(model, modelStrSize, MODEL_COACH); - } case 3: { + } case 1: { strcopy(model, modelStrSize, MODEL_ROCHELLE); } case 4: { strcopy(model, modelStrSize, MODEL_BILL); @@ -156,4 +156,72 @@ stock bool SpawnMinigun(const float vPos[3], const float vAng[3]) { delete trace; return false; } +} +//returns true if model found +stock bool GetSurvivorName(int client, char[] buffer, int length) { + + char modelName[38]; + GetClientModel(client, modelName, sizeof(modelName)); + if(StrContains(modelName,"biker",false) > -1) { + strcopy(buffer, length, "Francis"); + }else if(StrContains(modelName,"teenangst",false) > -1) { + strcopy(buffer, length, "Zoey"); + }else if(StrContains(modelName,"namvet",false) > -1) { + strcopy(buffer, length, "Bill"); + }else if(StrContains(modelName,"manager",false) > -1) { + strcopy(buffer, length, "Louis"); + }else if(StrContains(modelName,"coach",false) > -1) { + strcopy(buffer, length, "Coach"); + }else if(StrContains(modelName,"producer",false) > -1) { + strcopy(buffer, length, "Rochelle"); + }else if(StrContains(modelName,"gambler",false) > -1) { + strcopy(buffer, length, "Nick"); + }else if(StrContains(modelName,"mechanic",false) > -1) { + strcopy(buffer, length, "Ellis"); + }else{ + return false; + } + return true; +} + +stock int GetSurvivorType(const char[] modelName) { + if(StrContains(modelName,"biker",false) > -1) { + return 6; + }else if(StrContains(modelName,"teenangst",false) > -1) { + return 5; + }else if(StrContains(modelName,"namvet",false) > -1) { + return 4; + }else if(StrContains(modelName,"manager",false) > -1) { + return 7; + }else if(StrContains(modelName,"coach",false) > -1) { + return 2; + }else if(StrContains(modelName,"producer",false) > -1) { + return 1; + }else if(StrContains(modelName,"gambler",false) > -1) { + return 0; + }else if(StrContains(modelName,"mechanic",false) > -1) { + return 3; + }else{ + return false; + } +} + +stock bool GiveClientWeapon(int client, const char[] wpnName, bool lasers) { + char sTemp[64]; + float pos[3]; + GetClientAbsOrigin(client, pos); + Format(sTemp, sizeof(sTemp), "weapon_%s", wpnName); + + int entity = CreateEntityByName(sTemp); + if( entity != -1 ) { + DispatchSpawn(entity); + TeleportEntity(entity, pos, NULL_VECTOR, NULL_VECTOR); + + if(lasers) SetEntProp(entity, Prop_Send, "m_upgradeBitVec", 4); + + EquipPlayerWeapon(client, entity); + return true; + }else{ + return false; + } } \ No newline at end of file diff --git a/scripting/l4d2_ai_minigun.sp b/scripting/l4d2_ai_minigun.sp index a4c5a0f..1d6d89c 100644 --- a/scripting/l4d2_ai_minigun.sp +++ b/scripting/l4d2_ai_minigun.sp @@ -26,15 +26,14 @@ public Plugin myinfo = int g_iSurvivors[MAXPLAYERS+1], g_iLastSpawnClient, g_iAvoidChar[MAXPLAYERS+1] = {-1,...}; -public void OnPluginStart() -{ +public void OnPluginStart() { EngineVersion g_Game = GetEngineVersion(); - if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2) - { - SetFailState("This plugin is for L4D/L4D2 only."); + if(g_Game != Engine_Left4Dead2) { + SetFailState("This plugin is for L4D2 only."); } - RegAdminCmd("sm_spawn_minigun_bot", Command_SpawnAIBot, ADMFLAG_ROOT); + RegAdminCmd("sm_spawn_holdout_bot", Command_SpawnHoldoutBot, ADMFLAG_ROOT); + RegAdminCmd("sm_spawn_minigun_bot", Command_SpawnMinigunBot, ADMFLAG_ROOT); } public void OnMapStart() { @@ -53,7 +52,7 @@ public void OnClientPutInServer(int client) { } } -public Action Command_SpawnAIBot(int client, int args) { +public Action Command_SpawnMinigunBot(int client, int args) { char arg1[16]; if(args > 0) { GetCmdArg(1, arg1, sizeof(arg1)); @@ -74,7 +73,44 @@ public Action Command_SpawnAIBot(int client, int args) { //make sure spawns a little above vPos[2] += 1.0; - if(!SpawnSurvivor(vPos, vAng, model, true)) { + int survivor = SpawnSurvivor(vPos, vAng, model, true); + if(survivor > -1) { + GiveClientWeapon(survivor, "rifle_ak47", true); + }else{ + ReplyToCommand(client, "Failed to spawn survivor."); + } + }else{ + ReplyToCommand(client, "Usage: sm_spawn_minigun_bot <4=Bill, 5=Zoey, 6=Francis, 7=Louis>"); + } + return Plugin_Handled; +} + +public Action Command_SpawnHoldoutBot(int client, int args) { + char arg1[16]; + if(args > 0) { + GetCmdArg(1, arg1, sizeof(arg1)); + char model[64]; + if(!FindSurvivorModel(arg1, model, sizeof(model))) { + LogError("Could not find a survivor model."); + ReplyToCommand(client, "Could not find that survivor."); + return Plugin_Handled; + } + + //get ground: + float vPos[3], vAng[3]; + if(!GetGround(client, vPos, vAng)) { + LogError("Failed to find ground for survivor"); + ReplyToCommand(client, "Could not find a suitable ground location to spawn survivor."); + return Plugin_Handled; + } + //make sure spawns a little above + vPos[2] += 1.0; + + int survivor = SpawnSurvivor(vPos, vAng, model, false); + if(survivor > -1) { + GiveClientWeapon(survivor, "rifle_ak47", true); + SetEntProp(survivor, Prop_Send, "m_survivorCharacter", GetSurvivorType(model)); + }else{ ReplyToCommand(client, "Failed to spawn survivor."); } }else{ @@ -86,11 +122,11 @@ public Action Command_SpawnAIBot(int client, int args) { -stock bool SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] model, bool spawn_minigun) { +stock int SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] model, bool spawn_minigun) { int entity = CreateEntityByName("info_l4d1_survivor_spawn"); if( entity == -1 ) { LogError("Failed to create \"info_l4d1_survivor_spawn\""); - return false; + return -1; } //set character type (7 = Louis) DispatchKeyValue(entity, "character", "7"); @@ -114,7 +150,7 @@ stock bool SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] if( bot_user_id <= 0 || (bot_client_id = GetClientOfUserId(bot_user_id)) <= 0 ) { LogError("Failed to match survivor, did they not spawn? [%d/%d]", bot_user_id, bot_client_id); - return false; + return -1; } SetClientName(bot_client_id, "MinigunBot"); TeleportEntity(bot_client_id, vPos, NULL_VECTOR, NULL_VECTOR); @@ -122,12 +158,13 @@ stock bool SpawnSurvivor(const float vPos[3], const float vAng[3], const char[] if(spawn_minigun && !SpawnMinigun(vPos, vAng)) { LogError("Failed to spawn minigun for client #%d", bot_client_id); KickClient(bot_client_id, "AIMinigun:MinigunSpawnFailure"); - return false; + return -1; } TeleportEntity(bot_client_id, vPos, NULL_VECTOR, NULL_VECTOR); SetEntityModel(bot_client_id, model); CreateTimer(1.5, TimerMove, bot_user_id); - return true; + //probably return user_id? + return bot_client_id; } stock bool TraceFilter(int entity, int contentsMask) { if( entity <= MaxClients ) @@ -151,6 +188,7 @@ void AvoidCharacter(int type, bool avoid) case 5: set = 2; // Zoey case 7: set = 1; // Francis case 6: set = 0; // Louis + default: return; } SetEntProp(i, Prop_Send, "m_survivorCharacter", set); } else { @@ -177,4 +215,4 @@ Action TimerMove(Handle timer, any client) { SetEntityMoveType(client, MOVETYPE_NONE); TeleportEntity(client, NULL_VECTOR, NULL_VECTOR, view_as({ 0.0, 0.0, 0.0 })); } -} \ No newline at end of file +} diff --git a/scripting/l4d2_avoid_minigun.sp b/scripting/l4d2_avoid_minigun.sp index 568dad8..73500fd 100644 --- a/scripting/l4d2_avoid_minigun.sp +++ b/scripting/l4d2_avoid_minigun.sp @@ -64,6 +64,8 @@ public Action CheckTimer(Handle timer) { //todo: only teleport once? //TeleportEntity(bot, finalPos, NULL_VECTOR, NULL_VECTOR); L4D2_RunScript("CommandABot({cmd=1,bot=GetPlayerFromUserID(%i),pos=Vector(%f,%f,%f)})", GetClientUserId(bot), finalPos[0], finalPos[1], finalPos[2]); + }else{ + L4D2_RunScript("CommandABot({cmd=3,bot=GetPlayerFromUserID(%i)})", GetClientUserId(bot)); } } }