Um jetzt zu erreichen, dass ein vorheriges "Geflashtsein" berücksichtigt wird, habe ich folgende Ergänzungen vorgenommen:
Handle g_hTimerDisable = INVALID_HANDLE;
Handle g_hFlashTimer[MAXPLAYERS + 1];
bool g_bEnabled, g_bTeam, g_bDead, g_bSpec, g_bOwner, g_bDisable, g_bOverride, g_bLateLoad, g_bAlive[MAXPLAYERS + 1];
float g_fDisable, g_fLife;
int g_iTeam[MAXPLAYERS + 1], g_iFlashStartTime[MAXPLAYERS + 1];
...
public void OnMapEnd()
{
if(g_bEnabled)
{
if(g_hTimerDisable != INVALID_HANDLE && CloseHandle(g_hTimerDisable)) g_hTimerDisable = INVALID_HANDLE;
ClearArray(g_hEntities);
// ClearArray(g_hFlashTimer);
for(int i=0; i < MAXPLAYERS; i++)
{
if(g_hFlashTimer[i] != INVALID_HANDLE)
{
CloseHandle(g_hFlashTimer[i]);
g_hFlashTimer[i] = INVALID_HANDLE;
}
}
}
}
...
public Action Event_OnFlashPlayer(Handle event, const char[] name, bool dontBroadcast)
{
if(g_bEnabled)
{
int client = GetClientOfUserId(GetEventInt(event, "userid"));
if(!client || !IsClientInGame(client) || g_bDisable) return Plugin_Continue;
if(!g_bAlive[client])
{
if(g_bSpec && g_iTeam[client] <= CS_TEAM_SPECTATOR || g_bDead && g_iTeam[client] >= CS_TEAM_T)
SetEntPropFloat(client, Prop_Send, "m_flFlashMaxAlpha", 0.5);
}
else
{
int _iData[2];
if(GetArraySize(g_hEntities) == 0) return Plugin_Continue;
GetArrayArray(g_hEntities, 0, _iData);
if(g_iTeam[client] == _iData[1])
{
if(!g_bOwner && _iData[0] == client) return Plugin_Continue;
if(g_bTeam)
{
if(g_iFlashStartTime[client] > 0)
{
// Wenn der Client bereits geflasht ist und die Flash Duration noch nicht abgelaufen ist,
// dann berechnen wir die "Geflashtheit" anhand
// eines Zeitstempels und setzen diese als Startwert für die nächste Flash
// (in der Annahme die Flashanimation ist linear)
g_fFlashDur = GetEntPropFloat(client, Prop_Send, "m_flFlashDuration");
curTime = GetSysTickCount(); // GetTime()
int curFlashDur = curTime - g_iFlashStartTime[client];
// Sollte eigentlich immer der Fall sein...
if(curFlashDur < g_fFlashDur)
{
// "m_flFlashMaxAlpha" kann maximal den Wert 255 haben
float newFlashDur = (curFlashDur / (g_fFlashDur * 1000)) * 255;
SetEntPropFloat(client, Prop_Send, "m_flFlashMaxAlpha", newFlashDur);
}
}
else
{
SetEntPropFloat(client, Prop_Send, "m_flFlashMaxAlpha", 0.5);
}
}
}
else
{
// Timer "zurücksetzen" (löschen, einen neuen anlegen) und damit die Flash Duration zurücksetzen,
// wenn die nächste Gegnerflash kommt,
// bevor die vorherige abgelaufen ist -> Timer nach hinten verschieben
if(g_hFlashTimer[client] != INVALID_HANDLE)
{
CloseHandle(g_hFlashTimer[client]); // KillTimer()
g_hFlashTimer[client] = INVALID_HANDLE;
}
// Hier merken wir wann ein Client geflasht wurde
g_iFlashStartTime[client] = GetSysTickCount();
// Man könnte auch eine weniger flexible Konstante verwenden, anstatt sich das jedes Mal neu zu holen;
// Wert in Sekunden
g_fFlashDur = GetEntPropFloat(client, Prop_Send, "m_flFlashDuration");
// Timer der nach der Flash Duration den Status "Flashed" wieder zurücksetzt
g_hFlashTimer[client] = CreateTimer(g_fFlashDur, Unflash_Player, client);
}
}
}
return Plugin_Continue;
}
...
public Action Timer_Flash(Handle timer)
{
g_bDisable = true;
g_hTimerDisable = INVALID_HANDLE;
}
...
public Action Unflash_Player(Handle timer, int client)
{
g_iFlashStartTime[client] = 0;
// Brauchen wir das?
// return Plugin_Stop;
}
Display More
Kurze Erklärung (zusätzlich zu den Kommentaren im Code):
Wenn ein Spieler durch einen Gegner geflasht wurde, dann merke ich mir die "Systemzeit", wann das passiert ist, für diesen Spieler in einem Array. Zusätzlich wird ein Timer gestartet, der die Zeit des "Geflashtseins" abwartet und ihn dann wieder aus der Liste nimmt (genau genommen die Zeit des Flashens auf 0 setzt). Wenn der Spieler daraufhin, während er noch geflasht ist, eine Teamflash abbekommt, finden wir einen Eintrag (eine Zeit) in diesem Array. Anstatt den Spieler jetzt einfach zu "Entflashen", berechnen wir anhand der bereits abgelaufenen Zeit des "Geflashtseins" die restliche "Geflashtheit" aus. Diese wird dann als Startwert für die nächste Flash (in dem Fall eine Teamflash) weitergegeben. Damit wird die Teamflash nicht gecancelt, sondern nimmt die Eigenschaften der vorherigen Gegnerflash an und führt diese weiter.
Wenn jetzt aber nach der ersten Gegnerflash, während der Spieler noch geblendet ist, eine zweite Gegnerflash kommt, wird quasi die Flashdauer verlängert. Es muss erneut die gesamte Flashdauer abgewartet werden bis wir den Spieler als nicht geblendet vermerken.
Dieser Ansatz könnte das Problem stark mildern. Perfekt wird es nehme ich mal an nicht sein, aufgrund von Ping/Pingschwankungen, Timerungenauigkeiten, etc.
Bedenken habe ich aber noch einige, da ich hier mit vielen Annahmen gearbeitet habe und mich höchstwahrscheinlich in diesen irre. Ich gehe davon aus, dass die Flashdauer einen Maximalwert hat und bei jeder Gegnerflash mit diesem Wert angefangen wird. Das gilt auch für das "Geflashtsein".
Ich bin mir aber ziemlich sicher, dass dem nicht so ist und bspw. die Flashdauert in irgendeiner Weise addiert wird, wenn man nacheinander mehrere Gegnerflashes abbekommt. Ich denke man ist nach mehreren Flashes, die man direkt ins Gesicht bekommt länger blind als durch eine, die man direkt abbekommt.
Selbes Spiel beim Geflashtsein, denke das ganze wird dynamisch vom Server/Spiel pro Flash pro Spieler berechnet. Denn eine Flash zu der man etwas Distanz hat, wird einen nicht die volle Dauer flashen und nicht mit voller Stärke treffen.
Auch gehe ich davon aus, dass die Flashanimation von 100 -> 0 linear verläuft, aber da bin ich mir auch nicht ganz sicher.
Nur kenne ich diese Formeln nicht, sonst könnte man das miteinfließen lassen. Vielleicht findet man etwas im SourceSDK. Ich hab keine Ahnung.
Wisst ihr vielleicht etwas dazu? Kann man mit meinem Post etwas anfangen?
PS: Musste den Post jetzt kürzen bzw. aufteilen, da zu lang...
PS 2: Ist es nicht möglich etwas farblich in einem Codeblock zu hinterlegen?
Gruß
PRESSIVE