AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Scripting (https://forums.alliedmods.net/forumdisplay.php?f=107)
-   -   [L4D2]Spawn Infected couldn't find position 5 times. (https://forums.alliedmods.net/showthread.php?t=339897)

LinLinLin 10-07-2022 06:01

[L4D2]Spawn Infected couldn't find position 5 times.
 
2 Attachment(s)
i have do something like this.
PHP Code:

int cheat_client = -1;
for(
int i 1<= MaxClientsi++) 

    if(
IsClientInGame(i))
    {
         
cheat_client i;
         break;
     }
}
if( !
L4D_GetRandomPZSpawnPosition(cheat_client,class,5,{0.0,0.0,0.0}) )//这个玩家附近的位置, 类型, 次数, 无用的vec
{
    
LogMessage("找位失败, 正在重新找位.");
    
CreateTimer(1.0,Timer_CreateInfectedBotByClass,class,TIMER_FLAG_NO_MAPCHANGE);
    return;
}

int bot CreateFakeClient("Infected Bot");
if( 
bot != )
{
    
ChangeClientTeam(bot,TEAM_INFECTED);
    
KickClient(bot);
    switch(class)
    {
        case 
CLASS_CHARGER
        
CheatCommand(cheat_client"z_spawn_old""charger auto");
        case 
CLASS_HUNTER
        
CheatCommand(cheat_client"z_spawn_old""hunter auto");
        case 
CLASS_JOCKEY
        
CheatCommand(cheat_client"z_spawn_old""jockey auto");
        case 
CLASS_SMOKER
        
CheatCommand(cheat_client"z_spawn_old""smoker auto");
        case 
CLASS_BOOMER
        
CheatCommand(cheat_client"z_spawn_old""boomer auto");
        case 
CLASS_SPITTER
        
CheatCommand(cheat_client"z_spawn_old""spitter auto");
    }


It prevent most of the issue about "couldn't find position", but sometime it happend again.
I guess that maybe check position before spawn is not perfect. Harry said that CreateFakeClient is too expensive, and usually late out in tick.

I look up some .sp file about infected_bot_control, they use SDKCall(NextBotxxxxxxx) to spawn infectedbot, and use the return value of SDKCall to check whether it spawn correctly. But "z_spawn_old" cmd has no return value.

I think DHook z_spawn_old(const CCommand *) , get and check the return value will help, but i don't know how to do this because it return a warning() func in failed and i don't know which type of return is appropriate.

Can someone give a suggestion?

alasfourom 10-07-2022 10:00

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
Is this what you are trying to achieve?

"z_spawn_old charger auto" already spawn special infected in random position

I'm really not sure what do you want to do :roll:, also there are multiple plugins that can spawn special infected

PHP Code:

#include <sourcemod>

#pragma semicolon 1
#pragma newdecls required

public void OnPluginStart()
{
    
RegAdminCmd("sm_add_infected"Command_SpawnInfectedADMFLAG_UNBAN"To Spawn Random Infected");
}

public 
Action Command_SpawnInfected(int clientint args)
{
    
SpawnRandomInfected(client);
    
PrintToChatAll("\x04[Random Spawner] \x01Player \x03%N \x01has spawned random infected"client);
    return 
Plugin_Handled;
}

void SpawnRandomInfected(int client)
{
    
int spawn GetRandomInt(16);
    switch (
spawn)
    {
        case 
1CheatCommand(client"z_spawn_old""charger auto");
        case 
2CheatCommand(client"z_spawn_old""hunter auto");
        case 
3CheatCommand(client"z_spawn_old""smoker auto");
        case 
4CheatCommand(client"z_spawn_old""spitter auto");
        case 
5CheatCommand(client"z_spawn_old""boomer auto");
        case 
6CheatCommand(client"z_spawn_old""jockey auto");
    }
}

void CheatCommand(int client, const char[] command, const char[] item)
{
    
int CmdFlags GetCommandFlags(command);
    
SetCommandFlags(commandCmdFlags & ~FCVAR_CHEAT);
    
FakeClientCommand(client"%s %s"commanditem);
    
SetCommandFlags(commandCmdFlags);



LinLinLin 10-07-2022 15:48

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
1 Attachment(s)
Sorry, i forget to post the full func.
PHP Code:

void SpawnInfected(int class)
{
    if( !
g_gamemode_on || g_has_round_end)
        return;

    
int cheat_client = -1;
    for(
int i 1<= MaxClientsi++) 
    { 
        if(
IsClientInGame(i))
        {
            
cheat_client i;
            break;
        }
    }
    
    if( 
cheat_client == -)
    {
        
LogMessage("当前没有找到合法玩家执行 cmd 命令, 正在重新查找.");
        
CreateTimer(1.0,Timer_CreateInfectedBotByClass,class,TIMER_FLAG_NO_MAPCHANGE);
        return;
    }

    if( !
L4D_GetRandomPZSpawnPosition(cheat_client,class,5,{0.0,0.0,0.0}) )//这个玩家附近的位置, 类型, 次数, 无用的vec
    
{
        
LogMessage("找位失败, 正在重新找位.");
        
CreateTimer(1.0,Timer_CreateInfectedBotByClass,class,TIMER_FLAG_NO_MAPCHANGE);
        return;
    }

    
int bot CreateFakeClient("Infected Bot");
    if( 
bot != )
    {
        
ChangeClientTeam(bot,TEAM_INFECTED);
        
KickClient(bot);
        switch(class)
        {
            case 
CLASS_CHARGER
            
CheatCommand(cheat_client"z_spawn_old""charger auto");
            case 
CLASS_HUNTER
            
CheatCommand(cheat_client"z_spawn_old""hunter auto");
            case 
CLASS_JOCKEY
            
CheatCommand(cheat_client"z_spawn_old""jockey auto");
            case 
CLASS_SMOKER
            
CheatCommand(cheat_client"z_spawn_old""smoker auto");
            case 
CLASS_BOOMER
            
CheatCommand(cheat_client"z_spawn_old""boomer auto");
            case 
CLASS_SPITTER
            
CheatCommand(cheat_client"z_spawn_old""spitter auto");
        }
    }
    else
    {
        
LogMessage("FakeClient 创建失败, 正在重新创建.");
        
CreateTimer(1.0,Timer_CreateInfectedBotByClass,class,TIMER_FLAG_NO_MAPCHANGE);
    }


Most of thing is copy from l4d_infectedbot plugin, i just change some judge condition.
The problem is "Couldn't find a xxx spawn position in 5 tires"... This problem can't be fixed, so i want to hook this warning so that i can create a new timer to spawn it agian.

If don't do this, the amount of SI will not equal to the convar setting beacause it actually not create in game but plugin thought it has been created...

Create a repeat timer to check the count of SI seems not good and timely, i thought...
Sorry for my english.

LinLinLin 10-09-2022 14:20

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
好的,我想我大概知道怎麼做了
我在使用了一個全局 Arraylist 和一個全局計時器。
每3秒检查這個生成隊列

ok, maybe i know how to do it .
i use a global Arraylisy and a global repeat-timer.

PHP Code:

g_infected_spawn_queue = new ArrayList(1);
g_timer_infectedbot_spawn_queue CreateTimer(3.0,Timer_SpawnInfectedInQueue,_,TIMER_REPEAT); 

在特感生成的時候寫入(無論是否成功)
When spawn an infectedbot, it's type will be push in the arraylist whether it spawn successfully or not.
PHP Code:

void SpawnInfected(int class)
{
    
g_infected_spawn_queue.Push(class);


在特感成功生成的時候移除出隊列
The type of infectebot in arraylist will be remove when it trigger player_spawn event, as it spawn successfully.
PHP Code:

void Event_PlayerSpawnInfo(Event event, const char[] namebool dontBroadcast)
{
    
//省略了部分代碼
    
int index g_infected_spawn_queue.FindValue(type);
    if( 
index != -1)
    {
        
g_infected_spawn_queue.Erase(index);
    }


考慮到性能,每3秒僅生成隊列第一個特感
spawn too many infectedbot in once is not good, the timer will spawn one infectedbot and the type is the value in arraylist(0).

PHP Code:

Action Timer_SpawnInfectedInQueue(Handle timer)
{
    if( !
g_gamemode_on || g_has_round_end )
    {
        
g_timer_infectedbot_spawn_queue null;
        return 
Plugin_Stop;
    }
        

    if( 
g_infected_spawn_queue.Length == )
        return 
Plugin_Continue;
    
    
//生成查询队列里生成的特感.
    
int class = g_infected_spawn_queue.Get(0);
    
SpawnInfected(class);
    return 
Plugin_Continue;


經過測試,感覺3秒檢查和生成隊列首個特感比較合適。在多特情況下,最終章開啟機關後,特感緩慢 增加到設置的數量。
服務器sv 不會出現太大波動。
Now it seems good in my server. Infectedbot will respawn in order after it spawn failed. By setting 3 seconds timer, the infectedbot count will increase slowly when it can spawn.
And my server sv don't change radically.

Silvers 10-09-2022 15:34

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
So others can help you..

https://forums.alliedmods.net/misc.php?do=showrules

Quote:

This is an English language forum (other than a few specific, labelled subforums). If you're going to post in another language, also add the text in English, even if from online translator.

LinLinLin 10-09-2022 16:27

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
i forget it, sorry...

now add the translation.

KadabraZz 09-06-2023 18:47

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
Did you do this directly in a plugin that controls the spawn of the infected? This is really good, the same thing happens to me, spawning 10 special infections in the same second makes the SV go up which causes a temporary lag.

gabuch2 04-25-2024 19:40

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
Quote:

Originally Posted by KadabraZz (Post 2809799)
Did you do this directly in a plugin that controls the spawn of the infected? This is really good, the same thing happens to me, spawning 10 special infections in the same second makes the SV go up which causes a temporary lag.

I wonder if it's the same problem I've been having. Sadly, I've got no solution so far.

Since I use [L4D2] Balancer Spawn Infected which modifies the director instead of spawning SI directly, there's no way I can add a delay to the SI bots as suggested in other threads about a similar problem, so it constantly causes lag whenever it tried to spawn multiple SI at the same time.

I already checked my Spawn hooks to see if anything's too expensive, but everything looks fine and most expensive calculations are being checked if the client is survivor anyway so it doesn't apply.

Has anyone got any idea on where should I look to fix this?

Silvers 04-27-2024 11:52

Re: [L4D2]Spawn Infected couldn't find position 5 times.
 
There is no fix, creating clients is taxing on the server and will create a spike, the only solution is to delay the spawning of each SI. You could probably use Left4DHooks forwards L4D_OnSpawnTank and L4D_OnSpawnSpecial then add the class/pos details to an array, block spawning and spawn those from the array after 1 frame or 0.1 seconds.


All times are GMT -4. The time now is 20:28.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.