Gutawer wrote:What's the cleanest way to send out a hitscan from a position in 3d space? Spawning an actor to send out the hitscan seems to work nicely, but I can't figure out how to make it transfer the target to the actor that is "supposed" to have sent out the hitscan.
Is the target supposed to be the thing hit by the bullet? If so, you can do this one of two ways:
1. Use LineAttack in conjunction with passing an FTranslatedLineTarget struct. Check to see if the struct's "linetarget" exists.
Code:
// returned by AimLineAttack. struct FTranslatedLineTarget { Actor linetarget; double angleFromSource; double attackAngleFromSource; bool unlinked; // found by a trace that went through an unlinked portal.
native void TraceBleed(int damage, Actor missile); }
--- Or ---
2. Give the puff +HITTRACER, or HITMASTER flag, in addition to +PUFFGETOWNER. The puff will then set the entity hit as its own tracer/master, which the puff can then transfer that to the target pointer, which is the one who shot the bullet.
Method 1 would be best -- you can offset this hitscan along the Z axis as well.
Re: "How do I ZScript?"
Fri Nov 03, 2017 10:43 am
Can someone take my hand and lead me through process of creating custom property? I want armor which: If damage lower than yield limit armor will deflect all damage If damage higher than yield limit, but smaller than strength limit it will damaged only at 1 point of armor If damage higher than strength limit it will damaged to x point of armor, where x=round down((incoming damage)/(strengh limit))
So i write
Code:
class hard_armor : basicarmorpickup { int yield_limit; property hard_armor_yield_limit: yield_limit;
int strength_limit; property hard_armor_strength_limit: strength_limit;
Default { Armor.SaveAmount 600; Armor.SavePercent 0; Armor.MaxFullAbsorb 0; hard_armor.hard_armor_yield_limit: 15; hard_armor.hard_armor_strength_limit: 40; } States { Spawn: arm2 A 6; arm2 b 6 bright; loop; } }
And....what next?
Re: "How do I ZScript?"
Sun Nov 05, 2017 10:04 am
Override the Use function in the armor
Code:
//=========================================================================== // // ABasicArmorPickup :: Use // // Either gives you new armor or replaces the armor you already have (if // the SaveAmount is greater than the amount of armor you own). When the // item is auto-activated, it will only be activated if its max amount is 0 // or if you have no armor active already. // //===========================================================================
override bool Use (bool pickup) { let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
// This should really never happen but let's be prepared for a broken inventory. if (armor == null) { armor = BasicArmor(Spawn("BasicArmor")); armor.BecomeItem (); Owner.AddInventory (armor); } else { // If you already have more armor than this item gives you, you can't // use it. if (armor.Amount >= SaveAmount + armor.BonusCount) { return false; } // Don't use it if you're picking it up and already have some. if (pickup && armor.Amount > 0 && MaxAmount > 0) { return false; } }
And PlayerPawn's Damage(I don't remember the name) function to follow what ever rules its supposed to based on the items you add to it. I'm not sure but you may be able to access it directly from the variable?
Last edited by ZippeyKeys12 on Sun Nov 05, 2017 10:39 am, edited 1 time in total.
Re: "How do I ZScript?"
Sun Nov 05, 2017 10:12 am
I try make monster with custom hitbox area. The problem is that actor which embody parts of body much smaller than hitbox of desired monster, say imp. I must, and wish, insert all body part inside of hitbox that master-imp. But it make him completely unreachable for attacking, since all attack blocks by hitbox of that imp.
I already brute force all available combinations of flag and actor property in CanCollideWith without any satisfying result. Or master-imp dont let pass punch, or hitscan, or it dont block anything included player and other walking actor.
Now I try make it with infinitesimal radius and height. Thats works, body part can be wounded without problem, but monster can seep through any gap in the wall, door and other holes. How make it stop a_chase through hole, if volume for a_warp-ing body part actor is not enough?
Re: "How do I ZScript?"
Sun Nov 05, 2017 10:15 am
ZippeyKeys12 wrote:Override the Use function in the armor
Code:
//=========================================================================== // // ABasicArmorPickup :: Use // // Either gives you new armor or replaces the armor you already have (if // the SaveAmount is greater than the amount of armor you own). When the // item is auto-activated, it will only be activated if its max amount is 0 // or if you have no armor active already. // //===========================================================================
override bool Use (bool pickup) { let armor = BasicArmor(Owner.FindInventory("BasicArmor"));
// This should really never happen but let's be prepared for a broken inventory. if (armor == null) { armor = BasicArmor(Spawn("BasicArmor")); armor.BecomeItem (); Owner.AddInventory (armor); } else { // If you already have more armor than this item gives you, you can't // use it. if (armor.Amount >= SaveAmount + armor.BonusCount) { return false; } // Don't use it if you're picking it up and already have some. if (pickup && armor.Amount > 0 && MaxAmount > 0) { return false; } }
Can you comment what going on in every line, like for baby?
Change damageobj to
Spoiler:
Code:
override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0) { let what_armor = owner.FindInventory("hard_armor", /*true*/);
else if (what_armor != null) { int yield_limit = what_armor.hard_armor.hard_armor_yield_limit; int strength_limit = what_armor.hard_armor.hard_armor_strength_limit;
I`m not sure I use pointers right. And Is it necessary to change damagemobj at PlayerPawn? I cant attach it to armor directly?
Re: "How do I ZScript?"
Sun Nov 05, 2017 4:01 pm
I'm a bit busy right now, I believe it is TakeSpecialDamage you want to override. I can try and give you a rough example in a couple of hours if no one more qualified helps you out first. Also if you want code written/explained perhaps resource request would be better? I honestly have NO clue if that's correct, someone please correct me if it is not.
EDIT: To avoid double posting
Spoiler: Second Post
Extremely rough and not functional:
Code:
class HardArmor: basicarmor { int yield_limit; int strength_limit; override Inventory CreateCopy (Actor other) { // HardArmor is stored in the inv as HardArmor. // HardArmor that is in reserve is not. let copy = HardArmor(Spawn("HardArmor")); copy.SavePercent = SavePercent != 0 ? SavePercent : 0.33335; // slightly more than 1/3 to avoid roundoff errors. copy.Amount = Amount; copy.MaxAmount = MaxAmount; copy.Icon = Icon; copy.BonusCount = BonusCount; copy.ArmorType = ArmorType; copy.ActualSaveAmount = ActualSaveAmount; copy.yield_limit= yield_limit; copy. strength_limit= strength_limit; GoAwayAndDie (); return copy; } override bool HandlePickup (Inventory item) { if (item.GetClass() == "HardArmor") { // You shouldn't be picking up HardArmor anyway. return true; } if (!item.bIgnoreSkill) { if (item is "HardArmorPickup") { let armor = HardArmorPickup(item); armor.SaveAmount = int(armor.SaveAmount * G_SkillPropertyFloat(SKILLP_ArmorFactor)); } } return false; } override void AbsorbDamage (int damage, Name damageType, out int newdamage) { int saved;
if (!DamageTypeDefinition.IgnoreArmor(damageType)) { int full = MAX(0, MaxFullAbsorb - AbsorbCount);
if (Amount < saved) { saved = Amount; } newdamage -= saved; Amount -= saved; AbsorbCount += saved; if (Amount == 0) { // The armor has become useless SavePercent = 0; ArmorType = 'None'; // Not NAME_BasicArmor. // Now see if the player has some more armor in their inventory // and use it if so. As in Strife, the best armor is used up first. BasicArmorPickup best = null; Inventory probe = Owner.Inv; while (probe != null) { let inInv = BasicArmorPickup(probe); if (inInv != null) { if (best == null || best.SavePercent < inInv.SavePercent) { best = inInv; } } probe = probe.Inv; } if (best != null) { Owner.UseInventory (best); } } damage = newdamage; }
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player if ((damage > 0) && (ArmorType != 'None')) // BasicArmor is not going to have any damage factor, so skip it. { newdamage = ApplyDamageFactors(ArmorType, damageType, damage, damage); } } }
class HardArmorPickup :BasicArmorBonus{ int yield_limit; property YieldLimit: yield_limit;
int strength_limit; property StengthLimit: strength_limit; Default { Armor.SaveAmount 600; Armor.SavePercent 0; Armor.MaxFullAbsorb 0; hard_armor.YieldLimit: 15; hard_armor.StengthLimit: 40; } States { Spawn: arm2 A 6; arm2 b 6 bright; loop; } }
You'd have to add the yield and stuff calculations into hardarmor's absorbdamage function and also alter use in hardarmorpickup to set hardarmor's values. Honestly, it's too much for me to do right now. If you understand ZScript you should be able to do it, otherwise I'd recommend familiarizing yourself with the language itself so that you can do things like this on your own. Searching the source code or looking at this is the best for understanding the existing implementation of things in GZDoom
Also can one execute an arbitrary lump? and once more:
ZippeyKeys12 wrote:Also is it possible to register an EventHandler while the game is running? I recall seeing ZZYZX mention this, but I can't seem to figure it out. Also, is it not possible to put a constant array in a struct? Can I access a variable in an EventHandler from my StatusBar?
Thanks for any help
Last edited by ZippeyKeys12 on Sun Nov 05, 2017 7:52 pm, edited 1 time in total.
Re: "How do I ZScript?"
Mon Nov 06, 2017 4:37 pm
Question:
how do I initialize a dynamic array of class items?
I know how to declare it but I can't figure out how to initialize it. Array<classname> myArray = ..??
I can assure you that when I am posting something here, I have searched the wiki and the forums extensively, and tried myself. The wiki does not say how to initialize it, nor could I find an example. I have these parts in my code, and they are working properly; however, it's recommended to initiliaze it, and I simply don't know how.
Code:
Array<MQueuedMessage> messQueue; Array<MQueuedSpawn> spawnQueue; int ticks;
void QueueMessage(int ticsdelay, int line, int messnr) { let qm = new("MQueuedMessage"); qm.delay = ticks + ticsdelay; qm.line = line; qm.messnr = messnr; messQueue.Push(qm); // append item }