Hallo!
Wenn ein Spieler stirbt, werden seine Koordinaten unter OnPlayerDeath in der globalen Variable "pDeathLoc[MAX_PLAYERS][4]" erfasst, also X, Y, Z und facing angle.
public OnPlayerDeath(playerid, killerid, reason)
{
if(GetPlayerVirtualWorld(playerid) == 0)
{
SetPlayerHealth(playerid, FLOAT_INFINITY); //...um die Todesanimation zu überspringen und sofort wieder an der Todesposition zu spawnen
ClearAnimations(playerid);
GetPlayerPos(playerid, pDeathLoc[playerid][0], pDeathLoc[playerid][1], pDeathLoc[playerid][2]);
GetPlayerFacingAngle(playerid, pDeathLoc[playerid][3]);
}
}
In diesem Falle setze ich die HP des Spielers auf unendlich, sodass die Todesanimation übersprungen wird. Das führ zudem dazu, dass OnPlayerDeath und OnPlayerSpawn direkt aufeinander aufgerufen werden. Dass der Spieler gespawnt wird, heißt nach einem Tod aber nicht, dass er wieder am Leben ist, was bedeutet, dass die Spielervariable "IsPlayerDead[playerid]" auf true ist. Er ist viel mehr in einer Art "Downstate". Erst nach Ablauf des Timers oder die Betätigung eines CMD wird die Variable "IsPlayerDead[playerid]" auf false gesetzt, sodass der Spieler wieder als "lebendig" angesehen wird.
In einer Include vertiefe ich das Wiederbelebungssystem. An der Todesposition soll u.a. ein Mapicon gesetzt werden.
public OnPlayerDeath(playerid, killerid, reason)
{
if(GetPlayerVirtualWorld(playerid) == 0)
{
RezzMapIcon[playerid] = CreateDynamicMapIcon(pDeathLoc[playerid][0], pDeathLoc[playerid][1], pDeathLoc[playerid][2], 58, -1, 0, -1, -1, 100.0, MAPICON_LOCAL);
RezzLabel[playerid] = CreateDynamic3DTextLabel("", C_RED, pDeathLoc[playerid][0], pDeathLoc[playerid][1], pDeathLoc[playerid][2], 100.0, playerid, INVALID_VEHICLE_ID, 0, 0, -1, -1, 100.0); //Hier wird das Mapicon gesetzt
BleedOutTimer[playerid] = SetTimerEx("BleedOut", 1000, true, "i", playerid);
switch(pInfo[playerid][Language])
{
case LANGUAGE_DE: PlayerTextDrawSetString(playerid, BleedoutTD[playerid], "~r~30~w~~n~~n~~n~Druecke ~r~~k~~VEHICLE_ENTER_EXIT~~w~ um zu respawnen!");
case LANGUAGE_EN: PlayerTextDrawSetString(playerid, BleedoutTD[playerid], "~r~30~w~~n~~n~~n~Press ~r~~k~~VEHICLE_ENTER_EXIT~~w~ to respawn!");
}
PlayerTextDrawShow(playerid, BleedoutTD[playerid]);
}
return BO_OnPlayerDeath(playerid, killerid, reason);
}
Jetzt gibt es entweder die Möglichkeit im "Downstate" zu respawnen (CMD), zu verbluten (Timer) oder wiederbelebt zu werden (ebenfalls Timer).
CMD:respawn(playerid, params[])
{
RespawnPlayerAtHospital(playerid);
SetPlayerHealth(playerid, 100);
IsPlayerDead[playerid] = false;
ClearAnimations(playerid);
KillTimer(BleedOutTimer[playerid]);
BleedOutPoints[playerid] = 30;
PlayerTextDrawHide(playerid, BleedoutTD[playerid]);
DestroyDynamicMapIcon(RezzMapIcon[playerid]); //Mapicon wird zerstört
DestroyDynamic3DTextLabel(RezzLabel[playerid]);
return 1;
}
//oder
forward BleedOut(playerid);
public BleedOut(playerid)
{
if(!BeingRezzed[playerid]) //Spieler wird von niemandem wiederbelebt
{
BleedOutPoints[playerid]--;
new string3D[3],
stringTD[72];
format(string3D, sizeof(string3D), "%d", BleedOutPoints[playerid]);
UpdateDynamic3DTextLabelText(RezzLabel[playerid], C_RED, string3D);
switch(pInfo[playerid][Language])
{
case LANGUAGE_DE: format(stringTD, sizeof(stringTD), "~r~%d~w~~n~~n~~n~Druecke ~r~~k~~VEHICLE_ENTER_EXIT~~w~ um zu respawnen!", BleedOutPoints[playerid]);
case LANGUAGE_EN: format(stringTD, sizeof(stringTD), "~r~%d~w~~n~~n~~n~Press ~r~~k~~VEHICLE_ENTER_EXIT~~w~ to respawn!", BleedOutPoints[playerid]);
}
PlayerTextDrawSetString(playerid, BleedoutTD[playerid], stringTD);
}
if(BeingRezzed[playerid]) //Spieler wird von einem oder mehreren Spielern wiederbelebt
{
BleedOutPoints[playerid] += (2*PlayersRezzingPlayer[playerid]);
new string3D[3],
stringTD[72];
format(string3D, sizeof(string3D), "%d", BleedOutPoints[playerid]);
UpdateDynamic3DTextLabelText(RezzLabel[playerid], C_RED, string3D);
switch(pInfo[playerid][Language])
{
case LANGUAGE_DE: format(stringTD, sizeof(stringTD), "~r~%d~w~~n~~n~~n~Druecke ~r~~k~~VEHICLE_ENTER_EXIT~~w~ um zu respawnen!", BleedOutPoints[playerid]);
case LANGUAGE_EN: format(stringTD, sizeof(stringTD), "~r~%d~w~~n~~n~~n~Press ~r~~k~~VEHICLE_ENTER_EXIT~~w~ to respawn!", BleedOutPoints[playerid]);
}
PlayerTextDrawSetString(playerid, BleedoutTD[playerid], stringTD);
}
if(BleedOutPoints[playerid] < 0) //Der Spieler verblutet und respawnt
{
new stringTD[14];
switch(pInfo[playerid][Language])
{
case LANGUAGE_DE: format(stringTD, sizeof(stringTD), "Verblutet");
case LANGUAGE_EN: format(stringTD, sizeof(stringTD), "Bled to death");
}
PlayerTextDrawHide(playerid, BleedoutTD[playerid]);
GameTextForPlayer(playerid, stringTD, 3000, 5);
KillTimer(BleedOutTimer[playerid]);
DestroyDynamic3DTextLabel(RezzLabel[playerid]);
DestroyDynamicMapIcon(RezzMapIcon[playerid]); //Mapicon wird zerstört
BleedOutPoints[playerid] = 30;
cmd_respawn(playerid, "");
}
if(BleedOutPoints[playerid] >= 100) //Der Spieler wurde vollständig geheilt/wiederbelebt
{
SetPlayerPos(playerid, pDeathLoc[playerid][0], pDeathLoc[playerid][1], pDeathLoc[playerid][2]);
SetPlayerFacingAngle(playerid, pDeathLoc[playerid][3]);
KillTimer(BleedOutTimer[playerid]);
DestroyDynamic3DTextLabel(RezzLabel[playerid]);
DestroyDynamicMapIcon(RezzMapIcon[playerid]); //Mapicon wird zerstört
PlayerTextDrawHide(playerid, BleedoutTD[playerid]);
BleedOutPoints[playerid] = 30;
}
return 1;
}
Mal ein Beispiel:
Der Spieler stirbt. Ich weiß im moment nicht, ob man dann selbst als Spieler das Mapicon sofort auf seinem Radar sieht, aber ich seh es auf jeden Fall nicht. Das ist aber nicht das Problem.
Der Spieler respawnt und stirbt ein zweites Mal. Dieses Mal sehe ich das Mapicon von der vorherigen Todesposition!
Und das zieht sich so durch. Ich sehe nie das Mapicon von der momentanen Spielerposition, sondern immer auf den Koordinaten, wo der Spieler einen Tod zuvor gestorben ist!
Push!