Clonk Forge Hazard update

Hey :slight_smile:

ich hab schon im CMC Forum geschrieben, aber vllt ists nicht der richtige bereich, weshalb keiner antwortet. Deswegen copy paste ich meinen post mal hierher:

Muss ich mich auf clonkforge regisitrieren, oder kann ich auch hier meine Verbesserungen vorstellen?  (edit: merke gerade ich kann mich garnicht auf ClonkForge registrieren, da ich weder das spiel gekauft habe (freeware), noch ein Hauptarchiv oderso habe.)

Habe im Zuge meines Packs auch so einige Dinge f√ľr das Hazardpack gemacht, z.b dass Munition teilweise aufgenommen werden kann (also nicht nur immer ganze 50er packs oderso) und man die munition auch wieder ablegen kann.
Und auch die ‚ÄúBewachen‚ÄĚ funktion habe ich deutlich verbessert, sodass nun wirklich vern√ľnftig automatisch auf Feinde geschossen wird, mit einstellung des suchradius (es gibt ja noch weitere Funktionen, die eigentlich dann auch noch automatisch waffen besorgen sollten usw, die habe ich aber nicht weiter ausgebaut)

Ist schon nen Jahr her, wei√ü also grad nicht mehr alle verbesserungen ausm kopf‚Ķ Aber wenn ich was zu beitragen kann, w√ľrde ich mich nochmal durchw√ľhlen und schauen, was ich alles gemacht hab ^^

Hier mal die Threads die ich zu Hazard gemacht hatte:
https://clonkspot.org/forum/topic_show.pl?tid=348 (bewachen befehl)
https://clonkspot.org/forum/topic_show.pl?tid=420  (aliens sterben zu schnell durch melee schaden)
https://clonkspot.org/forum/topic_show.pl?tid=333¬†¬† (ein Waffeng√ľrtel gebastelt, welcher es einzelnen clonks erm√∂glicht mehr von einer bestimmten munition zu tragen)
https://clonkspot.org/forum/topic_show.pl?tid=316¬† (weniger f√ľr typische hazardszenarien, aber: teleporter, segu und controller sind im normalen spiel baubar und funktionieren)

PN an Newton am besten.

Moin Serpens

Sehr schön zu lesen dass jemand gemerkt hat dass ich ein Hazard update rausbringen möchte und Bugfixes sammle. Schreib ruhig alles hier rein, ich lese hier mit.

Welches Pack ist das denn von dem du sprichst? Dann w√ľrde ich einfach mal selbst durchgucken und schauen ob ich Patches finde die in das Originalpack wandern k√∂nnten. Die Sache mit Bewachen und den Aliens h√∂rt sich gut an. bei den beiden letzteren Sachen bin ich mir nicht sicher. Die Strukturelemente in Hazard sind nicht darauf ausgelegt gebaut zu werden.

Hast du die Endlosschleife, wenn man die Lasergranate in eine Ecke schmeisst, schon gefixt?

Ah, freut mich wenn ich was beitragen kann :slight_smile:

Hast du dir eine Deadline gesetzt, bis wann du fertig sein willst? Heute schaffe ich es nicht mehr, mein Pack durchzugehen und die Woche geht ja wieder los… vllt schaff ichs in der woche, aber eventuell erst nächstes wochenende.

Mein Pack habe ich noch nicht veröffentlicht, weil es noch nicht fertig ist.  Fehlen noch ein paar kleine Dinge und es alleine zu balancen schaffe ich vermutlich auch nicht… falls ich endlich mal wieder etwas mehr zeit habe (spätestens im winter), werde ich alles soweit fertigstellen, es hochladen und dann mit eurer Hilfe (alle aus dem forum), balancen.
Das Pack ist quasi ein Zusammenschluss aus allen Paketen die mir so ganz gut gefallen haben und ich gerne in Kombination spielen w√ľrde. Leider sind die vielen Pakete ja in der Regel nicht untereinander kompatibel und ich hab daf√ľr dann halt gesorgt und hier und da Bugfixes und Verbesserungen eingebaut.¬† Es ist dazu gedacht ein normales Clonk Siedelspiel zu haben, wo man sich durch die Zeitalter forschen kann, bis hin zu Hazard und den Hazard Ships.¬†¬† Dummerweise ist das Pack meine erste Programmierarbeit √ľberhaupt gewesen :smiley: Mittlerweile kann ich denke ich ganz gut programmieren (auch Python), aber mein Pack ist leider extremst durcheinander und verdammt un√ľbersichtlich. D.h. selbst wenn ich es dir geben w√ľrde, w√ľrdest du Wochen brauchen, um dich darin zurechtzufinden :smiley:

Also ich werd die Tage dann mal mein Pack durchstöbern und schauen, was ich noch so habe und den Code dazu auch raussuchen und hier posten :slight_smile:

Ja

So in den nächsten zwei Wochen wollte ich mit allem fertig sein. Inklusive playtesting allerdings.

Wenn du ansonsten noch helfen willst, oder auch jemand anders. Ich hätte da noch einige kleinere Bugs:

* an der Sentry Gun fliegen manchmal? irgendwie Raketen vorbei anstatt zu explodieren wenn ich nicht die Wand treffe. Fehlt da vielleicht eine Hitbox, IsBulletTarget oder sowas?
* Die No-Camping Regel scheint irgendwie kaputt zu sein. Die meldet jedenfalls viel zu häufig dass man campt
* Manchmal spawnt man immer oben links (position 0,0), keine Ahnung wieso

zur Segu:
Offensichtlich ist ja nur das Gestell ein Target und das scheint auch zu funktionieren (jedenfalls in meiner Version‚Ķ wei√ü nicht ob ich da bez√ľglich bullettarget was ver√§ndert habe :D)

Wie möchtest du es gelöst haben? Soll das Waffenteil, z.b MG, auch ein Bullettarget sein? Und dann eben einzeln zerstörbar sein, während das Gestell an sich intakt bleibt? Oder soll das Waffenteil den Schaden ans Gestell weiterleiten?

Hmm, das ist das Problem? Ach, dann mach ich einfach die Hitbox des Gestelles gr√∂√üer. (Mit gedrehter Waffe w√§re es wohl zu gro√ü, da die Hitbox von gedrehten Objekten ja sehr gro√ü ist) Vielen Dank f√ľr die Problemsuche!

Ich hoffe es wird hier alles korrekt angezeigt… ich speicher den text aber vorher auch nochmal in einer txt datei ab… und kann die hochladen oderso…

Zum Skript der hazardclonks:

Die readytofire function im Hazardclonk sollte so aussehen (so werden auch Waffen wie Bazooka ber√ľcksichtigt):

public func ReadyToFire() {     // nur aus bestimmten Aktionen feuern

   var a = GetAction();

   // In Gebäude
   if(Contained()) return(Contained()->~ReadyToFire());
   // Reitet
   if(IsRiding()) return(GetActionTarget()->~ReadyToFire());
   // Schiebt
   if(a S= "Push")
     if(GetActionTarget()->~IsWeapon())
       return(true);

   // Nur beim Laufen, Schwimmen oder Springen
   if(a eq "WalkArmed"
   || a eq "SwimArmed"
   || a eq "JumpArmed")
    return(true);

¬†¬† // wenn Waffe die nur im Zielen abgefeuert werden kann, ist die Aktion ohne "armed" und daher bisher unber√ľcksichtigt
   if(Contents()->~IsWeapon())
     if(Contents()->GetFMData(FM_Aim)>0)
       if(a eq "Walk" || a eq "None")    // nicht wenn waffe zum zielen aber schwimmend oder springend
       return(true);
  
   // JetpackFlight fehlt noch, sowie Aim*… das steht in den Funktionalitäten
   return(_inherited());
}


In der UpdateCharge Funktion habe ich kurz vrom return noch zugef√ľgt:
// pr√ľfen ob Waffe in Hand
  CheckArmed();

Ohne dies, wird CheckArmed meiner meinung nach viel zu selten gecheckt. (ich glaube nur wenn clonk sich bewegt?) Das hat zumindest in meiner Version zu problemen gef√ľhrt.

Die funktion Incineration sollte angepasst werden, ob nun so wie ich es gemacht habe, oder ob du ne bessere Idee hast, bleibt dir √ľberlassen :wink: . So wie sie bisher ist, sterben hazardclonk in Flammen sehr schnell (z.b brandbomben)

public func Incineration() {
  // Hazardclonks brennen ncht wirklich :wink:
  Extinguish();
if(!brennt)
  { // damit bei Brandbomben nicht sofort tot
  Schedule("DoDmg(5,DMG_Fire,0,1)",1,20,this());
  AddFireEffect(this(),30,FIRE_Red,1);
  brennt=1;
  ScheduleCall(0,"Feueristaus",20,0,0);
  }
}
func Feueristaus()
{brennt=0;}


Vor die Funktioin FXAggroTimer sollte noch ein Start zugef√ľgt werden:
public func FxAggroStart()
{
    // -> Waffen durchchecken, weil wenn nie zuvor geladene Waffe, dann funzt bewachen nicht.
    CheckIdleWeapon();
    return(1);
}


FxAggroTimer selbst sieht bei mir so aus:

public func FxAggroTimer(object pTarget, int no)
{
  // keine Waffe geladen? Dann waffen durchchecken 
// Waffenstatus durchgehen, vorher zählen
  var waffenanzahl = CustomContentsCount("IsWeapon");
   var o = 0;
   for(var u = 0; u < ContentsCount(); u++)
       if(Contents(u)->~IsWeapon())
      {
       if(!Contents(u)->~GetCharge()) ++o;
       if(Contents(u)->~GetCharge()) break;
      }
  // wenn o nun gleich waffenanzahl, dann heißt das, dass alle Waffen leer sind, dann nachladen.
   if(o == waffenanzahl)
   return(CheckIdleWeapon());

  // Wir haben ein Ziel?
  if(EffectVar(1, this(), no)) { EffectCall(this(), no, "Fire"); return(1); }
  // Zielen beenden
  if(IsAiming()) StopAiming();
//  Message("@No target", this());
  // Ziel suchen
  var dist = EffectVar(2, this(), no);
  var dir = GetDir()2-1;
  // Vorne
  var target = GetTarget(90
dir, 90,dist);
  // Hinten
  if(!target)
    if((!GetCommand() && !GetMacroCommand()) || EffectVar(0, this(), no) != 1)
      target = GetTarget(-90dir, 90,dist);
  // Gefunden?
  if(!target)
  {
    //Log("kein Ziel gefunden");
    // Nichts gefunden :frowning:
    // -> Bescheid geben!
    if(EffectVar(99, this(), no))
    {
      if(Contained())
        Contained()->~HandleAggroFinished(this());
      else if(IsRiding())
        GetActionTarget()->~HandleAggroFinished(this());
     
      EffectVar(99, this(), no);
    }
    // -> Waffen durchchecken
    CheckIdleWeapon();
    return();
  }
  // Super
  EffectVar(1, this(), no) = target;
  EffectVar(99,this(), no) = true; // wir haben ein Ziel \o/
}


FXAggroFire hat hier und da einige Verbessserungen, ich denke mal du kannst deine funktion mit dieser hier vergleichen und die unterscheide feststellen:
public func FxAggroFire(object pTarget, int no)
{

  // Zusatzhack: BR-Bombe!
  if(GetID(Contents()) == GBRB)
    // Nichts tun :C
    return();
  var y = EffectVar(4, this(), no);
  var x = EffectVar(3, this(), no);
  var dist = EffectVar(2, this(), no);
  var target = EffectVar(1, this(), no);
  var level = EffectVar(0, this(), no);
  var pathfree = true;
 
  // Nichts tun, wenn gerade verhindert
  if(ReadyToFire())
{

  // Fahrzeugsteuerung
  if(Contained())
  {
    if(Contained()->~HandleAggro(this(), level, target, dist, x, y))
      return(1);
    else
      return(AddCommand(this(), "Exit", 0,0,0,0,0,0,0, C4CMD_SilentSub));
  }
  if(IsRiding())
  {
    if(GetActionTarget()->~HandleAggro(this(), level, target, dist, x, y))
      return(1);
    else
      return(SetAction("Walk"));
  }
}
 
  // Zu weit von der Wachposition entfernt?
  if(level == 3) {
    if(Distance(GetX(), GetY(), x, y) > dist)
    {
      if(GetMacroCommand(1, 1) == target)
      {
        FinishMacroCommand(1,0,1);
        FinishMacroCommand(1);
      }
       // Log("zu weit von Wachposition entfernt");
      AddMacroCommand(0, "MoveTo", 0, x,y, 0, level);
      EffectVar(1, this(), no) = 0;
    //      Message("@Returning to guarded position", this());
      return();
    }
  }
 
  var maxdist = dist;
  if(!PathFree(GetX(), GetY(), target->GetX(), target->GetY()))
  {
    if(level == 1) maxdist = 0;
    if(level >= 2) maxdist = dist/2;
    pathfree = false;
  }
  //Log("kurz vor ziel weg");
  // Ziel irgendwie weg?
  // (Pathfree wurde schon gecheckt)…  reicht nicht, da zielen und schießen nicht aufhört, wenn was zwischen gegner, aber noch in Radius, und daher wird auch nicht nachgeladen -.-
  if(!CheckTarget(target,this,maxdist,0,0,true) || !PathFree(GetX(), GetY(), target->GetX(), target->GetY()))
    {
      EffectVar(1, this(), no) = 0;
      if(EffectVar(0, this(), no) == 2)
        ClearMacroCommands();
      if(!IsAiming()) if(Contents(0)) Contents(0)->~AimStop(); // damit auch das Autofeuer aufhört
      if(IsAiming())
        StopAiming();    
        //Log("Ziel iwie weg");
      return();
    }
¬† // Ich hab nix? ¬į-¬į
  if(!Contents()) return(); // Lauf, Forest, lauf!
  //Log("nach ich hab nix");
  // Waffe in die Hand nehmen
  if(!SelectWeapon(level, target, false))
    // Evtl. Feuermodus wechseln (dann muss erst nachgeladen werden, aber besser als nichts)
    if(!SelectWeapon(level, target, true))
    {
      // Bei Aggro_Follow können wir von unserem Pfade weg. D.h. eine Waffe und/oder Munition muss her
      if(GetAggroLevel() == Aggro_Follow)
      {
//      Message("@Searching for weapons / ammo", this());
        // Waffen auffrischen?
        if(CustomContentsCount("IsWeapon") <= 1)
          return(SearchWeapon(Aggro_Shoot));
        // Munition auffrischen
        return(SearchAmmo(Aggro_Shoot));
      }
      // ein Balrog, ein Feind gegen den ihr nichts ausrichten könnt…lauft!
        //Log("Balrog?");
        return();
    }
  // Stufe 1 - nur in die grobe Richtung ballern, lieber nicht anhalten oder sowas

  if(!ReadyToFire()) return();

  // Schaue ich in die richtige Richtung?
  if(GetX() < target->GetX())
  {
    if(GetDir() != DIR_Right)
      SetDir(DIR_Right);
  }
  else
  {
    if(GetDir() != DIR_Left)
      SetDir(DIR_Left);
  }
     //Log("kurz vor zielen muss auch mal sein");
  // Zielen, muss auch mal sein
if((!GetCommand() && !GetMacroCommand()) || level != 1 || IsAiming())
{
  if(pathfree && Contents()->GetBotData(BOT_Range) > 30) // Weg frei und keine Nahkampfwaffe?
  {
    var angle = Angle(GetX(), GetY(), target->GetX(), target->GetY());
    if(((!Inside(angle, 70, 120) && !Inside(angle, 250, 290)) || Contents()->GetFMData(FM_Aim)>0)
       //  && maxdist != 300 && ObjectDistance(target) < 300
)
    {
      if(!IsAiming()) StartSquatAiming();
      if(IsAiming())
      {
¬† ¬† ¬† //Log("zielen > 0 wird ausgef√ľhrt");
      var tx = target->GetX();
    var ty = target->GetY();
   
        if(Contents()->GetBotData(BOT_Ballistic))
          ty -= 15;
   
    DoMouseAiming(tx, ty);
      }
    }
    else
      if(IsAiming())
        StopAiming();
  }
  if(IsAiming() && !CheckAmmo(Contents()->GetFMData(FM_AmmoID), Contents()->GetFMData(FM_AmmoLoad), Contents(), this()))
     StopAiming();
}

   // Gut. Feuern wir bereits?
  if(Contents()->IsRecharging() || Contents()->IsShooting()) return();

  // Feuer!
  if(maxdist != 300 && pathfree) Control2Contents("ControlThrow");
//  Message("@My target: %s @%d/%d with level %d", this(), target->GetName(), target->GetX(), target->GetY(), level);
  // Stufe 2 - verfolgen!
  if(EffectVar(0, this(), no) >= 2)
    if(GetMacroCommand(1) ne "Follow" || GetMacroCommand(1, 1) != target)
      if(GetMacroCommand(0) ne "Follow" || GetMacroCommand(0,1) != target)
      {
        DebugLog("FxAggroFire - Adding Follow command","aggro");
        AddMacroCommand(0, "MoveTo", 0, GetX(),GetY(), 0, level);
        AddMacroCommand(0, "Follow", target, 0, 0, 0, level);
      }
  //Log("sollte gefeuert haben?");
}


Die funktion selectweapon braucht nur eine kleine Anpassung. hier mal die Funktion bis zur anpassung. Das was in der funktion danach folgt habe ich nicht verändert:
public func SelectWeapon(int iLevel, object pTarget, bool fFireModes)
{
¬† //Log("Selectweapon wird gepr√ľft");
  // Entfernung zum Ziel
  var dist = ObjectDistance(pTarget);
  // Keine Waffen in Inventar?
  if(!CustomContentsCount("IsWeapon")) return();
  // Bevorzugten Schadenstyp bestimmen
  var preftype = GetPrefDmgType(pTarget), type;
¬† // Alle durchgehen und passende pr√ľfen
  for(var i=0,obj,fav,mode,favmode ; obj = Contents(i) ; mode++)
  {
    // Nix Waffe
    if(!(obj->~IsWeapon())) { i++; mode = -1; continue; }
    // Feuermodus
    if(mode && !fFireModes) { i++; mode = -1; continue; }
    if(!(obj->GetFMData(FM_Name, mode))) { i++; mode = -1; continue; }
    if(mode == obj->GetFireMode() && mode) continue;
    // Nix gut… Hier wird jetzt auch die Aim Action von Bazooka und Co erkannt, weil damit sonst nicht geschossen wird -.-
    if(obj->GetFMData(FM_Aim, mode)>0)
      if(iLevel == 1 || (!WildcardMatch(GetAction(), "Walk") && !WildcardMatch(GetAction(), "Aim")))
        continue;


Ja ich glaube das wars an √Ąnderungen im Hazradclonk skript :slight_smile:

Ein Hazard appendto in strict im Hazard Ships pack, sorgt daf√ľr, dass Hazardclonks die Munition wieder ablegen k√∂nnen. Ich glaub ich habs f√ľr meine Zwecke noch ein wenig angepasst‚Ķ mindestens neue Munitionsarten hab ich zugef√ľgt.

Falls du das reinnehmen willst ins hazardpack‚Ķ muss man nat√ľrlich iwie drauf achten, dass es trotzdem noch kompatibel zu den ganzen Packs ist, die drauf aufbauen‚Ķ also z.b auch f√ľr das Hazard Ships pack‚Ķ naja, du wirst schon wissen, was okay ist und was nicht :slight_smile:

local ammobag;

protected func ContextAmmobag(object pCaller)
{
  [$AmmoBag$|Image=STAP|Condition=AmmoBagContextCheck]
  var ammo, x;
¬† //Men√ľ erzeugen
  CreateMenu(STAP,this(),0,0,GetName(0,ABAG),0,1,1);
¬† //Munition finden und hinzuf√ľgen
  while(ammo = Contents(x,ammobag))
  {
    // nur Ammo
    if(!(ammo ->~IsAmmo())) continue;
¬† ¬† //hinzuf√ľgen
    AddMenuItem(GetName(ammo),Format("PackAmmo(%i);",GetID(ammo)), GetID(ammo), this(), GetAmmo(GetID(ammo)),0,GetDesc(ammo));
    //Zählervariable erhöhen
    x++;
  }
  return(1);
}

protected func PackAmmo(ammo)
{
  var packed,pack_id,in_ammobag;
  if(ammo==STAM){ pack_id=STAP; packed=pack_id->AmmoCount();}
  if(ammo==ENAM){ pack_id=ENAP; packed=pack_id->AmmoCount();}
  if(ammo==GRAM){ pack_id=GRAP; packed=pack_id->AmmoCount();}
  if(ammo==GSAM){ pack_id=GSAP; packed=pack_id->AmmoCount();}
  if(ammo==MIAM){ pack_id=MIAP; packed=pack_id->AmmoCount();}
  if(ammo==SSTM){ pack_id=STLM; packed=pack_id->AmmoCount();}
  if(ammo==SHTM){ pack_id=SHMU; packed=pack_id->AmmoCount();}
  if(ammo==SPBT){ pack_id=SNI_; packed=pack_id->AmmoCount();}
  if(ammo==PTAM){ pack_id=PTAP; packed=pack_id->AmmoCount();}
  in_ammobag=GetAmmo(ammo);
  if(packed<=in_ammobag)
  {
    Sound("Click");
    DoAmmo(ammo,-packed);
    CreateObject(pack_id,AbsX(GetX()),AbsY(GetY()),GetOwner());
    ContextAmmobag(this());
    return(1);
  }
        if(packed>in_ammobag && 0<in_ammobag)
        {
  var muni=CreateObject(pack_id,AbsX(GetX()),AbsY(GetY()),GetOwner());
        muni ->~ RestAmmoreduzieren(packed-in_ammobag); // muni im paket wird um diese Zahl reduziert
  Sound("Click");
        DoAmmo(ammo,-in_ammobag);
        ContextAmmobag(this());
  return(1);
        }
  Sound("CommandFailure1");
  return(0);
}


Und das Skript f√ľr das Munitionspaket in strict sieht wie folgt aus. Es sorgt halt daf√ľr, dass man die munition teilweise aufnehmen kann und der Restwert im pack gespeichert wird und der Geldwert entsprechend berechnet wird. Zus√§tzlich noch ein paar kleinigkeiten wie einen Sound wenn es aufkommt und die m√∂glichkeit, dass es explodiert. (√ľbernimm, was du √ľbernehmem m√∂chtest :slight_smile: ) :


local verbraucht, value, restmunition, faktor;

public func IsAmmoPacket() { return(true); }
public func AmmoID()       { return(STAM); }
public func AmmoCount()    { return(50); }
public func AmmoCountRest() {return(AmmoCount()-verbraucht); }

// Damit eine variable Menge ausgegeben wird:
/* Initialisierung /

protected func Initialize()
{
  restmunition=AmmoCount();
  value = GetDefCoreVal("Value", "DefCore");
  faktor = (value
100)/restmunition;
}

/* Wert & Verkauf /

protected func CalcValue()
{
  var lastvalue = value;
  value = (restmunition
faktor)/100;
  return(lastvalue);
}

public HasAdditionalDesc: return(1);

public GiveAdditionalDesc:
  return(Format("Inhalt: %d Munition",restmunition));

func RestAmmoreduzieren(zahl)
{
verbraucht+=zahl;
//Log("Ammo reduziert");
restmunition=AmmoCountRest();
if(restmunition<=0) RemoveObject();
return(1);
}

protected func Hit()
{
Sound("RockHit*");
return (1);
}

private func OnTransfer() {}

protected func Activate(object pObj) {    // Doppelgraben
  return(TransferAmmo(pObj));
}

public func MayTransfer(object pObj)
{
  if(!pObj) return(false);
  var MaxAmmo;
  MaxAmmo = AmmoID()->~MaxAmmo(pObj);
  if(MaxAmmo)
// geändert, weil durch variable werte immer das maximum erreicht werden kann
    if(GetAmmo(AmmoID(),pObj) == MaxAmmo)
      return(false);
  return(true);
}

public func TransferAmmo(object pObj)    // Ammo dem Clonk geben
{
if(GetID(pObj)!=HZCK) {PlayerMessage(GetOwner(pObj),"Nur Hazardclonks können Munition aufnehmen",pObj); return(0);}

  var MaxAmmo;
  MaxAmmo = AmmoID()->~MaxAmmo(pObj);

  if(!pObj) return(false);
  if(NoAmmo()) return(false);
 
  // nicht wenn er schon zu viel hat
  if(!MayTransfer(pObj)) {
    PlayerMessage(GetOwner(pObj),"$NotMoreAmmo$",pObj,AmmoID());
    return();
  }

    if(GetAmmo(AmmoID(),pObj) + AmmoCountRest() <= MaxAmmo)
{
  // Nachricht ausgeben
  HelpMessage(GetOwner(pObj),"$Collected$",pObj,AmmoCountRest(),AmmoID());
  DoAmmo(AmmoID(),AmmoCountRest(),pObj);
  pObj->~AmmoTransferred();
  if(!OnTransfer()) RemoveObject();
  return(true);}

// wird auf MaxAmmo aufgestockt und die Restmunition im Pack reduziert
    if(GetAmmo(AmmoID(),pObj) + AmmoCountRest() > MaxAmmo)
{
var zahl=(MaxAmmo-GetAmmo(AmmoID(),pObj));
  // Nachricht ausgeben
  HelpMessage(GetOwner(pObj),"$Collected$",pObj,(MaxAmmo-GetAmmo(AmmoID(),pObj)),AmmoID());
  DoAmmo(AmmoID(),(MaxAmmo-GetAmmo(AmmoID(),pObj)),pObj);
  pObj->~AmmoTransferred();
  if(!OnTransfer()) {RestAmmoreduzieren(zahl);}

  return(true);}

}

protected func Damage()
{
  // Explodiert nicht, wenn er von einem Clonk getragen wird (Sonderregel gegen T-Flint-Superjumps)
  if (Contained())
    if (Contained()->~IsClonk())
    {
      Extinguish();
      return(0);
    }
  // Explosion - verzögert, um Endlosrekursion zu verhindern
  Schedule("Explode(20)", 1);
  return(1);
}

// Entz√ľndet sich bei Explosionstreffer
public func OnShockwaveHit(level, x, y)
{
Incinerate();
}

public func IsRefineryProduct() { return(1); }

Hier mal ne kleine Liste, von der dich vllt was interessieren könnte, vllt auch nicht ^^ :

Was h√§lst du von einer M√∂glichkeit die Z√ľndzeit von Granaten aus dem Granatwerfer einstellen zu k√∂nnen?
Ich hab dazu ein Clonk append geschrieben, um ein Men√ľ aufrufen zu k√∂nnen. Wenn man nen Granatwerfer tr√§gt, kann man damit dann halt die Z√ľndzeit einstellen, wann die Granate explodieren soll (bisher hat ja jede granate eingestellte standardwerte‚Ķ bei manchen sind diese meiner meinung nach aber oft zu kurz, oder auch mal zu lang, weshalb ich das eben eingebaut hab.

Ansonsten hab ich vom Flammernwerfer den Flammenball wieder aktiviert (warum war der deaktivert, ist er zu stark?) und hab die m√∂glichkeit zugef√ľgt auch pflanzen in Brand zu stecken und Eis zu schmelzen‚Ķ aber ich glaub das brauchste f√ľrs hazardpack nicht ^^

Au√üerdem hab ich f√ľr jede Waffe einen ‚Äúnur Geb√§ude‚ÄĚ Modus eingebaut. Man macht dann entweder nur clonks schaden, oder nur geb√§uden. Ist f√ľr hazard vermutlich aber auch nicht wichtig ^^

Bei den Minen habe ich Fake-Minen zugef√ľgt. Sind im prinzip dieselben Minen, nur dass sie nicht explodieren bzw. eine FakeExplosion verwenden und keinen schaden machen. Ist ganz nett um Gegner zu t√§uschen.

Achso bez√ľglich der Aliens, die zu schnell sterben: Ich denke dazu testest du selbst mal, wie schnell die Aliens sterben, wenn du ihnen Dinge gegen den Kopf schmei√üt :wink: Ich glaub Jumper sterben sofort und Berserker nach 2-3 Treffern oderso‚Ķ Also gegebenenfalls die Melee Resistenz erh√∂hen.¬† Ach und vllt noch zuf√ľgen, dass Leichen von Berserken und Co verroten (also kleiner werden und verschwinden).¬†

Da du ja vermutlich der hauptentwickler von Hazard bist: Ich finde euer Pack super toll! :D¬† Besonders die Lichteffekte gefallen mir, da es in meinem Pack auch Tag und dunkle nacht mit wechselndem Kriegsnebel usw gibt :slight_smile: Leider leider sorgen viele lichtkegel f√ľr starken Lag, was ich hier schon angesprochen hatte: https://clonkspot.org/forum/topic_show.pl?tid=402¬† (da siehst du auch einen Screenshot von meinem Pack)¬† Vllt kannst du ja zu den bisherigen Antworten noch was dazu zu sagen :)¬†¬† Ich hab √ľbrigens auch in mein Pack eingebaut, dass man die Farbe/intensit√§t jedes einzelnen Lichtes w√§hrend des Spiels beliebig ver√§ndern kann :smiley: eig nutzlos, aber ich fands lustig xD

Nochmal zu Aliens: Die W√ľrmer sollten noch gefixt werden. Und zwar, wenn man sie zu nah am Kartenrand platziert, wandert ihr Kopf au√üerhalb der Karte und wird quasi abgetrennt :D¬† Ich find die Stelle im Skript grad nicht mehr, aber ich hab glaub ich einfach daf√ľr gesorgt, dass sie ihren Kopf niemals zu nah an den Kartenrand bewegen d√ľrfen.

Die Drohne braucht glaube ich auch einen kleinen Fix. Wenn man ihr einen Clonk zum bewachen zugeteilt hat, folgt sie diesem ja. Aber wenn der Clonk ein Geb√§ude oder Fahrzeug betritt, dreht die Drohne durch :smiley: Sie fliegt dann einfach steil nach oben in die Unendlichkeit und wird iwann wieder zur√ľck geportet ^^¬† Habe das bisher noch nicht gefixt.

Die Fahrzeuge Shuttle und Panzer: Die verschiedenen Einzelteile sollten in der DefCore einen NoGet und NoSell Eintrag haben. Sonst machen sie Probleme, wenn sie in einem Geb√§ude sind. Zwar nicht so wichtig f√ľr Hazard, aber ich denke das sollte man trotzdem richten.
Achja, wo wir bei NoGet und NoSell sind: das gilt auch f√ľr das Lichtobjekt :wink: Wenn man ein leuchtendes objekt in ein Geb√§ude bringt, kann man sonst das Licht einzeln ausw√§hlen ^^

Die Munitionsg√ľrtel
, welche daf√ľr sorgen, dass ein Clonk mehr von einer bestimmmten Munition tragen kann, wolltest du nicht aufnehmen oder? Dachte eig schon, dass die ganz gut ins Pack passen w√ľrden. Aber muss ja nicht sein :slight_smile:

F√ľrs bewachen habe ich unterschiedliche Radien w√§hlbar gemacht. Welchen man w√§hlen sollte h√§ngt dann haupts√§chlich von der Reichweite der getragenen waffe ab. Ich denke man kann das men√ľ auch noch sch√∂ner gestalten als ich es jetzt gemacht habe (feste w√§hlbare werte), z.b frei einstellbare Werte zwischen 0 und 1000.
Möchtest du das aufnehmen?

Ach und ich habe einen Men√ľpunkt im Clonk bzw CanAim zugef√ľgt, wenn er eine Waffe dabei hat, kann man einstellen wie pr√§zise man zielen m√∂chte.
Mit der normalen Clonksteuerung sind die Steps ja leider ziemlich gro√ü, sodass ein pr√§zises zielen (besonders bei hohen entfernungen wichtig) fast nicht m√∂glich ist. Bei Jump&Run ist das deutlich einfacher. Deswegen kann man im Men√ľ nun hin und herschalten, ob man die standard gro√üen spr√ľnge haben will, mit denen man relativ schnell anvisieren kann, oder ob man kleine steps haben will, mit denen man pr√§ziser zielen kann, was aber daf√ľr etwas l√§nger dauert, weil halt kleine steps ^^
Möchtest du das aufnehmen?

1. Wozu ist das? Den Raketenwerfer soll man ja gerade nicht abfeuern ohne zu zielen

2. Der Check geh√∂rt da aber nicht hin. Ich habe stattdessen ein CheckArmed in Collection2, Grab und ControlSpecial hinzugef√ľgt

3. Check! Per Effekt gelöst, danke!


public func Incineration(int iPlr) {
  // Hazardclonks brennen ncht wirklich :wink:
  Extinguish();
  AddFireEffect(this(),30,FIRE_Red,1);
  AddEffect("FireDamage",this,100,1,this,0,30,5,iPlr);
}

protected func FxFireDamageStart(object pTarget, int iEffectNumber, int iTemp, int iDuration, int iDamage, int iPlr)
{
  if(iTemp) return;
  EffectVar(0,pTarget,iEffectNumber) = iDuration;
  EffectVar(1,pTarget,iEffectNumber) = iDamage;
  EffectVar(2,pTarget,iEffectNumber) = iPlr;
}

protected func FxFireDamageTimer(object pTarget, int iEffectNumber, int iEffectTime)
{
  DoDmg(EffectVar(1,pTarget,iEffectNumber), DMG_Fire, pTarget, 1, EffectVar(2,pTarget,iEffectNumber)+1);
 
  if(EffectVar(0,pTarget,iEffectNumber) < iEffectTime)
    return -1;
}

protected func FxFireDamageEffect(string szNewEffectName, object pTarget, int iEffectNumber, int iNewEffectNumber)
{
  if(szNewEffectName S= "FireDamage") return -2;
}

protected func FxFireDamageAdd(object pTarget, int iEffectNumber, string szNewEffectName, int iNewEffectTimer, int iDuration, int iDamage, int iPlr)
{
  EffectVar(0,pTarget,iEffectNumber) = iDuration;
  EffectVar(1,pTarget,iEffectNumber) = iDamage;
  EffectVar(2,pTarget,iEffectNumber) = iPlr;
}


4. Wozu, das macht er doch schon in 5.

5. Check! Funktional gleich eingebaut.
  var hasWeapons = false;
  var hasLoadedWeapon = false;
  for(var i = 0; i < ContentsCount(); i++)
  {
    if(Contents(i)->~IsWeapon())
    {
      hasWeapons = true;
      if(Contents(i)->~GetCharge() > 0)
      {
        hasLoadedWeapon = true;
        break;
      }
    }
  }
   
  if(hasWeapons && !hasLoadedWeapon)
  {
    CheckIdleWeapon();
    return;
  }


6. Ein paar Sachen dazu:

* Du hast //  && maxdist != 300 && ObjectDistance(target) < 300 auskommentiert. Die Stelle liest sich so dass die KI nur auf Targets zielt die näher als 300 px dran sind, wie verstehst du die Zeile? Und warum hast du sie auskommentiert?
* Der Rest h√∂rt sich sinnvoll an, √ľbernommen. Kannst Du mir sagen was das genau fixt? (Du hast statt bei !ReadyToFire() direkt gleich am Anfang abzubrechen noch eine ganze Reihe von Dingen ausgef√ľhrt)

7. Check. (!WildcardMatch(GetAction(), "Walk") && !WildcardMatch(GetAction(), "Aim*")) durch !(ReadyToAim() || IsAiming()) ersetzt, ansonsten deinen Fix √ľbernommen

> Was h√§lst du von einer M√∂glichkeit die Z√ľndzeit von Granaten aus dem Granatwerfer einstellen zu k√∂nnen?


Ne, das m√∂chte ich nicht √ľbernehmen, das wird zu komplex.

>Ansonsten hab ich vom Flammernwerfer den Flammenball wieder aktiviert (warum war der deaktivert, ist er zu stark?) und hab die m√∂glichkeit zugef√ľgt auch pflanzen in Brand zu stecken und Eis zu schmelzen.. aber ich glaub das brauchste f√ľrs hazardpack nicht ^^


Steckt der Flammenwerfer in Hazard keine Pflanzen in Brand? Das wäre schade. Den Flammenball hatten wir glaube ich deaktiviert weil er entweder buggy war und/oder scheiße aussah und niemand den noch polishen wollte. Wie sieht deiner denn aus?

> Au√üerdem hab ich f√ľr jede Waffe einen "nur Geb√§ude" Modus eingebaut. Man macht dann entweder nur clonks schaden, oder nur geb√§uden. Ist f√ľr hazard vermutlich aber auch nicht wichtig ^^


Ja.

> Bei den Minen habe ich Fake-Minen zugef√ľgt. Sind im prinzip dieselben Minen, nur dass sie nicht explodieren bzw. eine FakeExplosion verwenden und keinen schaden machen. Ist ganz nett um Gegner zu t√§uschen.


Nette Idee, passt aber nicht so recht ins Hauptpack.

> Achso bez√ľglich der Aliens, die zu schnell sterben: Ich denke dazu testest du selbst mal, wie schnell die Aliens sterben, wenn du ihnen Dinge gegen den Kopf schmei√üt ;) Ich glaub Jumper sterben sofort und Berserker nach 2-3 Treffern oderso... Also gegebenenfalls die Melee Resistenz erh√∂hen.  Ach und vllt noch zuf√ľgen, dass Leichen von Berserken und Co verroten (also kleiner werden und verschwinden). 


Werde ich untersuchen. Die Berserkerleiche fadet jetzt auch aus.

> Lichter


Siehe Zapper, Sven2 und Co. Da kann man leider nichts machen, außer die Lichter auszuschalten.

> Wurm


Ist notiert.

> Die Drohne


Die habe ich schon komplett √ľberarbeitet. Mal die Betaversion auf Clonkforge angeguckt?

> NoGet und NoSell


Ist notiert.

> Die Munitionsg√ľrtel


Naja, gibts denn da ne h√ľbsche Grafik dazu? Hast du da dann 6 verschiedene G√ľrtel oder wie?

> F√ľrs bewachen habe ich unterschiedliche Radien


Eher nicht, aber ich meine man kann noch andere Parameter festlegen, e.g. wie aggressiv der Clonk sein soll. Ob er nur rumsteht und schießt oder ob er sich auch umherbewegt, habe ich das richtig in Erinnerung?
Dann k√∂nnte man einen zweiten Modus hiinzuf√ľgen, "Defend position" und "Look out for enemies" oder sowas.

> Men√ľpunkt im Clonk bzw CanAim zugef√ľgt


Nein, gleiches Argument wie bei den einstellbaren Granaten. Ich will es simpel halten.

Das hört sich sinnvoll an. Ich werde es mir anschauen.

> Achja, wo wir bei NoGet und NoSell sind: das gilt auch f√ľr das Lichtobjekt ;) Wenn man ein leuchtendes objekt in ein Geb√§ude bringt, kann man sonst das Licht einzeln ausw√§hlen


Lichter haben schon NoGet und NoSell.

Ich antworte mal auf diesen Post, ohne die anderen antworten von dir gelesen zu haben.

>1. Wozu ist das? Den Raketenwerfer soll man ja gerade nicht abfeuern ohne zu zielen


Ich bin mir gerade nicht sicher, wie sich das auf die M√∂glichkeiten des Abfeuerns auswirkt‚Ķ aber ich konnte mit meinen ver√§nderungen die Bazooka nicht ohne zu zielen abfeuern. Der Sinn der √Ąnderung ist, dass im FxAggroFire die funktion readytofire gepr√ľft wird. Und mit einer Bazooka in der Hand w√§re der Clonk dann niemals ready to fire (man kann ihn in den zielmodus versetzen, aber wenn man ihm dann den befehl zum bewachen gibt, beendet er den zielmodus -> ich glaube ohne diese anpassung gehts nicht)
edit2: wobei… ich erinnere mich, dass ich kurzzeitig tatsächlich probleme damit hatte, dass die bazooka ohne zu zielen während des laufens abfeuerbar war… ich weiß aber nicht mehr, was ich dagegen gemacht habe…

>2. Der Check geh√∂rt da aber nicht hin. Ich habe stattdessen ein CheckArmed in Collection2, Grab und ControlSpecial hinzugef√ľgt


Ich hab ihn da eingef√ľgt, weil die fkt ja durch einen timer alle x sekunden ausgef√ľhrt wird. Dadurch w√§re es egal, was man dr√ľckt oder nicht dr√ľckt. Wird es bei deiner Umsetzung denn jetzt ausgef√ľhrt, wenn die Waffe gerade frisch aufgenommen wurde?  Ich bin mir wie gesagt nicht mehr sicher, aber ich glaube das Problem war halt, dass obwohl der Clonk eine Waffe dabei hatte, seine Action nicht Walkarmed war. Erst wenn er sich bewegt wird die action gesetzt. Dh. man brauch etwas, dass die action auch dann setzt, wenn man √ľberhaupt nichts mit dem clonk macht. Ist das in deiner L√∂sung der Fall (bin mir grad nicht mehr sicher, wann collection2 und grab aufgerufen werden)

>4. Wozu, das macht er doch schon in 5.


Theoretisch gut denkbar, dass ich manches √ľberfl√ľssigerweise doppelt gemacht habe, nach dem motto doppelt h√§lt besser :D
Habs grad getestet und ja, es funzt auch ohne :D

>6. Ein paar Sachen dazu:


    >Du hast //  && maxdist != 300 && ObjectDistance(target) < 300 auskommentiert. Die Stelle liest sich so dass die KI nur auf Targets zielt die n√§her als 300 px dran sind, wie verstehst du die Zeile? Und warum hast du sie auskommentiert?

Das hab ich quasi in einem späteren Post beantwortet. hatte erst nicht dran gedacht ^^ Und zwar soll die Distanz bei mir individuell einstellbar sein.

>Der Rest h√∂rt sich sinnvoll an, √ľbernommen. Kannst Du mir sagen was das genau fixt? (Du hast statt bei !ReadyToFire() direkt gleich am Anfang abzubrechen noch eine ganze Reihe von Dingen ausgef√ľhrt)


ich wei√ü leider nicht mehr, warum ich das !ReadytoFire so weit nach unten verschoben habe und kann es gerade auch nicht ganz nachvollziehen‚Ķ Zus√§tzlich hab ich ja einen if ReadytoFire Block um die Fahrzeugsteuerung gemacht. Auch das kann ich gerade nicht mehr nachvollziehen, warum ich das gemacht habe, denn in der RadytoFire funktion selbst, wird Contained() und Riding ja direkt ber√ľcksichtigt.
Das ist immer so eine Sache, mit der ich zu k√§mpfen habe, wenn ich mich l√§nger nicht mehr mit meinem Geschreibsel besch√§ftigt habe :D Ich wei√ü dann nicht, ob ich damals mist gebaut habe, weils halt alles noch so neu f√ľr mich war, oder ob ich nur meine damaligen guten gr√ľnde nicht mehr wei√ü :D  Also w√ľrde ich sagen, schau du nochmal, was deiner Meinung nach mehr Sinn ergibt‚Ķ
edit2:‚Ķ ich glaube ich hatte die !readytofire funktion nach unten verschoben, bevor ich die funktion selbst f√ľr die bazooka angepasst hatte. Jetzt wo sie f√ľr bazooka angepasst ist, sollte die position weiter vorne wieder okay sein.

edit:
Um ganz sicher zu gehen, dass dir meine fixes nicht das Paket versauen, teste sie am besten alle erstmal in einer neuen Kopie :D