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());
}
// prüfen ob Waffe in Hand
CheckArmed();
public func Incineration() {
// Hazardclonks brennen ncht wirklich ;)
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;}
public func FxAggroStart()
{
// -> Waffen durchchecken, weil wenn nie zuvor geladene Waffe, dann funzt bewachen nicht.
CheckIdleWeapon();
return(1);
}
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(-90*dir, 90,dist);
// Gefunden?
if(!target)
{
//Log("kein Ziel gefunden");
// Nichts gefunden :(
// -> 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/
}
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?");
}
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;
public func Incineration(int iPlr) {
// Hazardclonks brennen ncht wirklich ;)
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;
}
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;
}
// && 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?(!WildcardMatch(GetAction(), "Walk") && !WildcardMatch(GetAction(), "Aim*"))
durch !(ReadyToAim() || IsAiming())
ersetzt, ansonsten deinen Fix übernommen
>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
>4. Wozu, das macht er doch schon in 5.
>6. Ein paar Sachen dazu:
>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)
>>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.
> 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.
>Das mag durchaus sinnvoll sein, jedoch hast du sie eben nur auskommentiert und nciht etwa ersetzt durch einen Check abhängig von der Reichweite er Waffe.
ObjectDistance(target) < maxdist
um zu gewährleisten, dass er erst zielt, wenn das ziel nah genug ist.>> 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.
>Welche funktion hast du für die Bazooka angepasst? SelectWeapon?
> Dann aber gemerkt wie ich das problem löse, indem ich in redaytofire einfach den bazookateil einfüge und vergessen das !readytofire wieder an die ursprungsstelle zu packen ^^
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);
}
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); }
> Was hälst du von einer Möglichkeit die Zündzeit von Granaten aus dem Granatwerfer einstellen zu können?
>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 ;) 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).
> Lichter
> Wurm
> Die Drohne
> NoGet und NoSell
> Die Munitionsgürtel
>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?
>Die habe ich schon komplett überarbeitet. Mal die Betaversion auf Clonkforge angeguckt?
>Naja, gibts denn da ne hübsche Grafik dazu? Hast du da dann 6 verschiedene Gürtel oder wie?
> 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
> Fürs bewachen habe ich unterschiedliche Radien
> Menüpunkt im Clonk bzw CanAim zugefügt
>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.
>Nein, gleiches Argument wie bei den einstellbaren Granaten. Ich will es simpel halten.
//funktioniert nicht bei Spielerclonks...
func Attttack(idImage, pCaller)
{
// nur schießen
SetAggroLevel(Aggro_Shoot);
Sound("Confirm*");
}
//funktioniert nicht bei Spielerclonks...
func Fooollow(idImage, pCaller)
{
// schießen und stück verfolgen
SetAggroLevel(Aggro_Follow);
Sound("Confirm*");
}
>Ja wenn du das mit der Distanz dann so hinbekommst wäre das natürlich super ;)
Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill