-
NPC Leben pro Sekunde abziehen
Hi,
ich habe mal wieder ein kleines Problemchen, bei dem ich leider selbst nicht weiter weiß. Und zwar habe ich versucht, einen Giftpfeil zu erstellen. Dazu habe ich erstmal das hier ganz oben in die B_AssessDamage() geschrieben:
Code:
var int rnd; rnd = Hlp_Random (100);
var C_ITEM DistanceWeapon; DistanceWeapon = Npc_GetReadiedWeapon(other);
if (DistanceWeapon.munition == ItRw_DIV_Arrow_Special_03)
{
if (rnd <= 75)
{
var oCViewStatusBar bar_focus; bar_focus = MEM_PtrToInst (MEM_GAME.focusBar);
var int bar_tex; bar_tex = bar_focus.value_bar;
ViewPtr_SetTexture(bar_tex, "BAR_HEALTH_POISONED.TGA");
FF_ApplyOnceExt(DIV_SetPoisonHealth, 1000, 10);
} else {
return;
};
};
Die Textur des Lebensbalkens des getroffenen NPCs soll sich also ändern und dann soll die DIV_SetPoisonHealth Funktion aufgerufen werden, die so aussieht:
Code:
func void DIV_SetPoisonHealth ()
{
Npc_ChangeAttribute (self, ATR_HITPOINTS, -10);
FF_ApplyOnceExt(DIV_SetNormalHealthbarAgain, 10000, 1);
};
So weit funktioniert das auch. Aber das Leben wird bei dem getroffenen NPC nicht abgezogen. Die Funktion wird aber aufgerufen, denn wenn ich self mit hero tausche (also Npc_ChangeAttribute (hero, ATR_HITPOINTS, -10); ), verliert der Held 10 Sekunden lang pro Sekunde 10 Lebenspunkte. Auch mit victim habe ich es schon probiert, aber das funktioniert genau so wenig. Was müsste ich also machen, damit der getroffene NPC die 10 HP verliert?
(PS: Ich weiß, dass der Lebensbalken im moment noch bei allen NPCs geändert wird. Weiß nur noch nicht genau, wie ich das nur für den getroffenen NPC ändern kann. ^^)
-
Was das Abziehen der Lebensenergie angeht, solltest du es lösen können, wenn du einfach die Instanz-ID des NPC mitgibst.
Code:
if (!FF_ActiveData(DIV_SetPoisonHealth, Hlp_GetInstanceID(self))) {
FF_ApplyExtData(DIV_SetPoisonHealth, 1000, 10, Hlp_GetInstanceID(self));
};
Code:
func void DIV_SetPoisonHealth(slfInstID)
{
var C_NPC slf; slf = Hlp_GetNpc(slfInstID);
Npc_ChangeAttribute(slf, ATR_HITPOINTS, -10);
FF_ApplyOnceExt(DIV_SetNormalHealthbarAgain, 10000, 1);
};
EDIT: Für ApplyData gibt es keine "Once"-Funktion. Daher solltest du selbst abfragen, ob die FF schon läuft. Siehe Änderungen im Code.
Geändert von mud-freak (29.04.2017 um 15:45 Uhr)
-
Zitat von mud-freak
Was das Abziehen der Lebensenergie angeht, solltest du es lösen können, wenn du einfach die Instanz-ID des NPC mitgibst.
Code:
if (!FF_ActiveData(DIV_SetPoisonHealth, Hlp_GetInstanceID(self))) {
FF_ApplyExtData(DIV_SetPoisonHealth, 1000, 10, Hlp_GetInstanceID(self));
};
Code:
func void DIV_SetPoisonHealth(slfInstID)
{
var C_NPC slf; slf = Hlp_GetNpc(slfInstID);
Npc_ChangeAttribute(slf, ATR_HITPOINTS, -10);
FF_ApplyOnceExt(DIV_SetNormalHealthbarAgain, 10000, 1);
};
EDIT: Für ApplyData gibt es keine "Once"-Funktion. Daher solltest du selbst abfragen, ob die FF schon läuft. Siehe Änderungen im Code.
Super, vielen Dank.
Allerdings meckert Gothic jetzt, dass in der Zeile 128 eine Klammer ')' fehlt:
Code:
func void DIV_SetPoisonHealth (slfInstID)
-
Da hab ich was vergessen.
Code:
func void DIV_SetPoisonHealth(var int slfInstID)
-
Zitat von mud-freak
Da hab ich was vergessen.
Code:
func void DIV_SetPoisonHealth(var int slfInstID)
Danke, jetzt funktioniert es genau so, wie ich es mir vorgestellt habe.
Nur jetzt wäre da noch das Problem mit dem Balken, dass die Textur sich bei allen NPCs ändert. Ich kenne mich mit LeGo leider immer noch so gut wie gar nicht aus. Könntest du mir noch sagen, wie ich das anstelle, dass die sich nur beim getroffenen NPC ändert? Ich hab nämlich keine Idee was ich da im Skript ändern muss.
-
Ich selbst würde das auf eine wahrscheinlich etwas kompliziertere Art und Weise machen (mit Hooks, wenn die Engine die Healthbar anzeigt). Eine einfachere Variante wäre, das mit einer FrameFunction zu machen. Ich habe gerade keine Skripte hier, hier also nur ein halb-richtiger Gedankenanstoss.
Diese Funktion hier muss als FrameFunction durchgängig aufgerufen werden und aktualisiert die Fokusbar je nach NPC:
Code:
func void DIV_UpdatePoisonHealthbar() {
// Standardtextur
var string correctTex; correctTex = "BAR_HEALTH.TGA"; // Ich weiss nicht genau wie die heisst
// Überprüfe den aktuellen Fokus auf einen NPC
var oCNpc her; her = Hlp_GetNpc(hero);
if (Hlp_Is_oCNpc(her.focus_vob)) {
var C_NPC focusNpc; focusNpc = _^(her.focus_vob);
// Ist der NPC im Fokus vergiftet?
if (FF_ActiveData(DIV_SetPoisonHealth, Hlp_GetInstanceID(focusNpc)))
correctTex = "BAR_HEALTH_POISONED.TGA";
};
};
// Hole die Healthbartextur
var oCViewStatusBar focusBar; focusBar = _^(MEM_GAME.focusBar);
var int focusBarTex; focusBarTex = focusBar.value_bar;
// Muss die Textur aktualisiert werden?
if (!Hlp_StrCmp(ViewPtr_GetTexture(focusBarTex), correctTex)) {
ViewPtr_SetTexture(focusBarTex, correctTex);
};
};
Geändert von mud-freak (29.04.2017 um 18:43 Uhr)
-
Zitat von mud-freak
Ich selbst würde das auf eine wahrscheinlich etwas kompliziertere Art und Weise machen (mit Hooks, wenn die Engine die Healthbar anzeigt). Eine einfachere Variante wäre, das mit einer FrameFunction zu machen. Ich habe gerade keine Skripte hier, hier also nur ein halb-richtiger Gedankenanstoss.
Diese Funktion hier muss als FrameFunction durchgängig aufgerufen werden und aktualisiert die Fokusbar je nach NPC:
Code:
func void DIV_UpdatePoisonHealthbar() {
// Standardtextur
var string correctTex; correctTex = "BAR_HEALTH.TGA"; // Ich weiss nicht genau wie die heisst
// Überprüfe den aktuellen Fokus auf einen NPC
var oCNpc her; her = Hlp_GetNpc(hero);
if (Hlp_Is_oCNpc(her.focus_vob)) {
var C_NPC focusNpc; focusNpc = _^(her.focus_vob);
// Ist der NPC im Fokus vergiftet?
if (FF_ActiveData(DIV_SetPoisonHealth, Hlp_GetInstanceID(focusNpc)))
correctTex = "BAR_HEALTH_POISONED.TGA";
};
};
// Hole die Healthbartextur
var oCViewStatusBar focusBar; focusBar = _^(MEM_GAME.focusBar);
var int focusBarTex; focusBarTex = focusBar.value_bar;
// Muss die Textur aktualisiert werden?
if (!Hlp_StrCmp(ViewPtr_GetTexture(focusBarTex), correctTex)) {
ViewPtr_SetTexture(focusBarTex, correctTex);
};
};
Scheint perfekt zu funktionieren, danke.
Jetzt muss ich das ganze nur auch noch irgendwie für den Helden machen. Aber das krieg ich schon irgendwie hin.. hoffe ich.
-
Ich bin ein bisschen überrascht, dass es direkt funktioniert. Für den Spieler sollte das ganze genauso funktionieren. Anstatt einer weitere FrameFunction, kannst du die Färbung der Healthbar vom Spieler natürlich in die bestehende hinzufügen, damit es übersichtlich bleibt.
Wenn du alles zum Laufen gebracht hast, könntest du den Code vielleicht hier noch einmal in seiner Gesamtheit posten. Ich bin sicher, das Skript könnte für andere auch von Interesse sein. (Ich habe schon von Implementierungen gehört, die die gesamten Healthbars komplett entfernen und selbst neu erstellen. Da ist dein Ansatz um Längen besser, einfacher und performanter.)
-
-
Zitat von Bloodfly91
Anscheinend wird die B_AssessDamage() gar nicht für den Helden aufgerufen. Wie mache ich das jetzt also mit dem?
Schau dir dazu am besten mal den Post ganz unten (und den darin verlinkten) an. Vielleicht solltest du den Fall für NPCs auch so behandeln.
Das könnte dann so aussehen (InitDamage wie LeGo in der INIT_Global eintragen):
Code:
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg) {
// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden.
// Hole die betroffenen (N)PCs, hier gesetzt wie in der B_AssessDamage
var C_NPC slf; slf = _^(victimPtr);
var C_NPC oth; oth = _^(attackerptr);
// Überprüfe die benutzte Waffe wie gehabt (dein Auszug aus der B_AssessDamage)
// { ...
// Starte die FrameFunction. Dabei spielt es keine Rolle ob das Opfer der Spieler ist oder nicht
// };
// Damage unberührt zurückgeben
return dmg;
};
func void _DMG_OnDmg() {
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI);
};
func void InitDamage() {
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg);
dmg = 1;
};
Dann musst du nur noch die FF DIV_UpdatePoisonHealthbar um die Healthbar des Spielers erweitern.
-
Zitat von mud-freak
Schau dir dazu am besten mal den Post ganz unten (und den darin verlinkten) an. Vielleicht solltest du den Fall für NPCs auch so behandeln.
Das könnte dann so aussehen ( InitDamage wie LeGo in der INIT_Global eintragen):
Code:
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg) {
// Diese Funktion anpassen, wenn ihr den Schaden verändern wollt! 'dmg' ist der von Gothic berechnete Schaden.
// Hole die betroffenen (N)PCs, hier gesetzt wie in der B_AssessDamage
var C_NPC slf; slf = _^(victimPtr);
var C_NPC oth; oth = _^(attackerptr);
// Überprüfe die benutzte Waffe wie gehabt (dein Auszug aus der B_AssessDamage)
// { ...
// Starte die FrameFunction. Dabei spielt es keine Rolle ob das Opfer der Spieler ist oder nicht
// };
// Damage unberührt zurückgeben
return dmg;
};
func void _DMG_OnDmg() {
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI);
};
func void InitDamage() {
const int dmg = 0;
if (dmg) { return; };
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg);
dmg = 1;
};
Dann musst du nur noch die FF DIV_UpdatePoisonHealthbar um die Healthbar des Spielers erweitern.
Ok, dann werd ich mal versuchen das einzubauen. Vielen Dank schon mal.
-
So, hier nochmal das komplette Skript (das hoffentlich funktioniert, hat es jedenfalls, als ich es getestet habe. ).
Code:
func int DMG_OnDmg(var int victimPtr, var int attackerPtr, var int dmg)
{
var C_NPC slf; slf = _^(victimPtr);
var C_NPC oth; oth = _^(attackerptr);
var int rnd; rnd = Hlp_Random (100);
// Hier wird eingetragen, was vergiften kann. In diesem Fall nur Blutfliegen.
// Man könnte hier aber auch noch Waffen etc. eintragen.
if (Hlp_GetInstanceID(oth) == Hlp_GetInstanceID(Bloodfly))
|| (Hlp_GetInstanceID(oth) == Hlp_GetInstanceID(YBloodfly))
{
if (rnd <= 55)
{
if (!FF_ActiveData(SetPoisonHealth, Hlp_GetInstanceID(slf)))
{
// Die Funktion wird insgesamt 10 mal aufgerufen und 1 mal pro Sekunde.
// Kann auch geändert werden.
FF_ApplyExtData(DIV_SetPoisonHealth, 1000, 10, Hlp_GetInstanceID(slf));
};
};
};
return dmg;
};
func void _DMG_OnDmg()
{
EDI = DMG_OnDmg(EBP, MEM_ReadInt(MEM_ReadInt(ESP+644)+8), EDI);
};
func void InitDamage()
{
const int dmg = 0;
if (dmg)
{
return;
};
HookEngineF(6736583/*0x66CAC7*/, 5, _DMG_OnDmg);
dmg = 1;
};
Code:
func void SetPoisonHealth (var int slfInstID)
{
var C_NPC slf; slf = Hlp_GetNpc(slfInstID);
Npc_ChangeAttribute(slf, ATR_HITPOINTS, -10); // Schaden (pro Sekunde). Kann beliebig verändert werden.
};
func void UpdatePoisonHealthbar()
{
// Standardtextur
var string correctTex; correctTex = "BAR_HEALTH.TGA"; // Lebensbalken des NPCs
var string correctTexPlayer; correctTexPlayer = "BAR_HEALTH.TGA"; // Lebensbalken des PCs
// Falls der PC vergiftet ist
var oCNpc her; her = Hlp_GetNpc(hero);
if (FF_ActiveData(SetPoisonHealth, Hlp_GetInstanceID(her)))
{
correctTexPlayer = "BAR_HEALTH_POISONED.TGA";
};
// Überprüfe ob sich ein NPC im Fokus befindet
if (Hlp_Is_oCNpc(her.focus_vob))
{
var C_NPC focusNpc; focusNpc = _^(her.focus_vob);
// Falls der NPC im Fokus vergiftet ist
if (FF_ActiveData(SetPoisonHealth, Hlp_GetInstanceID(focusNpc)))
{
correctTex = "BAR_HEALTH_POISONED.TGA";
};
};
// Hole die Healthbartextur
var oCViewStatusBar focusBar; focusBar = _^(MEM_GAME.focusBar);
var oCViewStatusBar hpBar; hpBar = _^(MEM_GAME.hpBar);
var int focusBarTex; focusBarTex = focusBar.value_bar;
var int hpBarTex; hpBarTex = hpBar.value_bar;
// Muss die Textur des NPCs aktualisiert werden?
if (!Hlp_StrCmp(ViewPtr_GetTexture(focusBarTex), correctTex))
{
ViewPtr_SetTexture(focusBarTex, correctTex);
// Muss die Textur des PCs aktualisiert werden?
} else if (!Hlp_StrCmp(ViewPtr_GetTexture(hpBarTex), correctTexPlayer)) {
ViewPtr_SetTexture(hpBarTex, correctTexPlayer);
};
};
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|