From 5ef1930045deefcb438804f2f9ea3451ad43f4cc Mon Sep 17 00:00:00 2001 From: Gingerbeard Date: Thu, 24 Oct 2024 01:16:01 -0400 Subject: [PATCH 1/3] [fixed] pickup crash Fixes a crash that causes --- Entities/Common/Controls/StandardControls.as | 3 - Entities/Common/Controls/StandardPickup.as | 435 ++++++++----------- 2 files changed, 180 insertions(+), 258 deletions(-) diff --git a/Entities/Common/Controls/StandardControls.as b/Entities/Common/Controls/StandardControls.as index 69135fc51..0fac4d767 100755 --- a/Entities/Common/Controls/StandardControls.as +++ b/Entities/Common/Controls/StandardControls.as @@ -10,9 +10,6 @@ int zoomLevel = 1; // we can declare a global because this script is just used b void onInit(CBlob@ this) { this.set_s32("tap_time", getGameTime()); - CBlob@[] blobs; - this.set("pickup blobs", blobs); - this.set_u16("hover netid", 0); this.set_bool("release click", false); this.set_bool("can button tap", true); this.addCommandID("pickup"); diff --git a/Entities/Common/Controls/StandardPickup.as b/Entities/Common/Controls/StandardPickup.as index 28b46e626..2fd09b1ba 100644 --- a/Entities/Common/Controls/StandardPickup.as +++ b/Entities/Common/Controls/StandardPickup.as @@ -1,20 +1,19 @@ // Standard menu player controls // add to blob and sprite +#define CLIENT_ONLY + #include "StandardControlsCommon.as" #include "ActivationThrowCommon.as" #include "WheelMenuCommon.as" #include "KnockedCommon.as" -const u32 PICKUP_ERASE_TICKS = 80; +u16[] pickup_netids; +u16[] closest_netids; +u16 hover_netid = 0; void onInit(CBlob@ this) { - CBlob@[] blobs; - this.set("pickup blobs", blobs); - CBlob@[] closestblobs; - this.set("closest blobs", closestblobs); - this.getCurrentScript().runFlags |= Script::tick_myplayer; this.getCurrentScript().removeIfTag = "dead"; @@ -69,15 +68,14 @@ void onInit(CBlob@ this) menu.add_entry(PickupWheelMenuEntry("Crate", "$crate$", "crate", Vec2f(-16.0f, 0))); menu.add_entry(PickupWheelMenuEntry("Bucket", "$filled_bucket$", "bucket")); } - } void onTick(CBlob@ this) { if (this.isInInventory() || isKnocked(this)) { - this.clear("pickup blobs"); - this.clear("closest blobs"); + pickup_netids.clear(); + closest_netids.clear(); return; } @@ -94,11 +92,8 @@ void onTick(CBlob@ this) GatherPickupBlobs(this); - CBlob@[]@ pickupBlobs; - this.get("pickup blobs", @pickupBlobs); - CBlob@[] available; - FillAvailable(this, available, pickupBlobs); + FillAvailable(this, available); for (uint i = 0; i < menu.entries.length; i++) { @@ -128,12 +123,11 @@ void onTick(CBlob@ this) { TapPickup(this); - CBlob @carryBlob = this.getCarriedBlob(); + CBlob@ carryBlob = this.getCarriedBlob(); if (this.isAttached()) // default drop from attachment { - int count = this.getAttachmentPointCount(); - + const int count = this.getAttachmentPointCount(); for (int i = 0; i < count; i++) { AttachmentPoint @ap = this.getAttachmentPoint(i); @@ -150,7 +144,7 @@ void onTick(CBlob@ this) } else if (carryBlob !is null && !carryBlob.hasTag("custom drop") && (!carryBlob.hasTag("temp blob"))) { - ClearPickupBlobs(this); + pickup_netids.clear(); client_SendThrowCommand(this); this.set_bool("release click", false); } @@ -168,52 +162,47 @@ void onTick(CBlob@ this) PickupWheelMenuEntry@ selected = cast(menu.get_selected()); set_active_wheel_menu(null); - if (selected !is null && !selected.disabled) + if (selected is null || selected.disabled) return; + + CBlob@[] blobsInRadius; + if (getMap().getBlobsInRadius(this.getPosition(), this.getRadius() + 50.0f, @blobsInRadius)) { - CBlob@[] blobsInRadius; - if (this.getMap().getBlobsInRadius(this.getPosition(), this.getRadius() + 50.0f, @blobsInRadius)) + uint highestPriority = 0; + float closestScore = 600.0f; + CBlob@ closest; + + for (uint i = 0; i < blobsInRadius.length; i++) { - uint highestPriority = 0; - float closestScore = 600.0f; - CBlob@ closest; + CBlob@ b = blobsInRadius[i]; - for (uint i = 0; i < blobsInRadius.length; i++) + string bname = b.getName(); + for (uint j = 0; j < selected.options.length; j++) { - CBlob@ b = blobsInRadius[i]; + PickupWheelOption@ selectedOption = @selected.options[j]; + if (bname != selectedOption.name) continue; - string bname = b.getName(); - for (uint j = 0; j < selected.options.length; j++) + if (!canBlobBePickedUp(this, b)) break; + + float maxDist = Maths::Max(this.getRadius() + b.getRadius() + 20.0f, 36.0f); + float dist = (this.getPosition() - b.getPosition()).Length(); + float factor = dist / maxDist; + + float score = getPriorityPickupScale(this, b, factor); + + if (score < closestScore || selectedOption.priority > highestPriority) { - PickupWheelOption@ selectedOption = @selected.options[j]; - if (bname == selectedOption.name) - { - if (!canBlobBePickedUp(this, b)) - { - break; - } - - float maxDist = Maths::Max(this.getRadius() + b.getRadius() + 20.0f, 36.0f); - float dist = (this.getPosition() - b.getPosition()).Length(); - float factor = dist / maxDist; - - float score = getPriorityPickupScale(this, b, factor); - - if (score < closestScore || selectedOption.priority > highestPriority) - { - highestPriority = selectedOption.priority; - closestScore = score; - @closest = @b; - } - } + highestPriority = selectedOption.priority; + closestScore = score; + @closest = @b; } } + } - if (closest !is null) - { - // NOTE: optimisation: use selected-option-blobs-in-radius - @closest = @GetBetterAlternativePickupBlobs(blobsInRadius, closest); - client_Pickup(this, closest); - } + if (closest !is null) + { + // NOTE: optimisation: use selected-option-blobs-in-radius + @closest = @GetBetterAlternativePickupBlobs(blobsInRadius, closest); + client_Pickup(this, closest); } } @@ -225,79 +214,56 @@ void onTick(CBlob@ this) { GatherPickupBlobs(this); - CBlob@[]@ closestBlobs; - this.get("closest blobs", @closestBlobs); - closestBlobs.clear(); + closest_netids.clear(); CBlob@ closest = getClosestBlob(this); if (closest !is null) { - closestBlobs.push_back(closest); - /* - if (this.isKeyJustPressed(key_action1)) // pickup - { - server_Pickup(this, this, closest); - this.set_bool("release click", false); - } - */ + closest_netids.push_back(closest.getNetworkID()); } - } if (this.isKeyJustReleased(key_pickup)) { - if (this.get_bool("release click")) + if (this.get_bool("release click") && closest_netids.length > 0) { - CBlob@[]@ closestBlobs; - this.get("closest blobs", @closestBlobs); - if (closestBlobs.length > 0) - { - client_Pickup(this, closestBlobs[0]); - } + CBlob@ closest = getBlobByNetworkID(closest_netids[0]); + client_Pickup(this, closest); } - ClearPickupBlobs(this); + pickup_netids.clear(); } } } void GatherPickupBlobs(CBlob@ this) { - CBlob@[]@ pickupBlobs; - this.get("pickup blobs", @pickupBlobs); - pickupBlobs.clear(); - CBlob@[] blobsInRadius; + pickup_netids.clear(); - if (this.getMap().getBlobsInRadius(this.getPosition(), this.getRadius() + 50.0f, @blobsInRadius)) + CBlob@[] blobsInRadius; + if (getMap().getBlobsInRadius(this.getPosition(), this.getRadius() + 50.0f, @blobsInRadius)) { for (uint i = 0; i < blobsInRadius.length; i++) { - CBlob @b = blobsInRadius[i]; - + CBlob@ b = blobsInRadius[i]; if (b.canBePickedUp(this)) { - pickupBlobs.push_back(b); + pickup_netids.push_back(b.getNetworkID()); } } } } -CBlob@ GetBetterAlternativePickupBlobs(CBlob@[] available_blobs, CBlob@ reference) +CBlob@ GetBetterAlternativePickupBlobs(CBlob@[] available, CBlob@ reference) { - if (reference is null) - return reference; - - CBlob@[] blobsInRadius; const string ref_name = reference.getName(); const u32 ref_quantity = reference.getQuantity(); Vec2f ref_pos = reference.getPosition(); - CBlob @result = reference; + CBlob@ result = reference; - for (uint i = 0; i < available_blobs.length; i++) + for (uint i = 0; i < available.length; i++) { - CBlob @b = available_blobs[i]; - Vec2f b_pos = b.getPosition(); - if ((b_pos - ref_pos).Length() > 10.0f) - continue; + CBlob@ b = available[i]; + if ((b.getPosition() - ref_pos).Length() > 10.0f) continue; const string name = b.getName(); const u32 quantity = b.getQuantity(); @@ -308,18 +274,14 @@ CBlob@ GetBetterAlternativePickupBlobs(CBlob@[] available_blobs, CBlob@ referenc return result; } -void ClearPickupBlobs(CBlob@ this) -{ - this.clear("pickup blobs"); -} - -void FillAvailable(CBlob@ this, CBlob@[]@ available, CBlob@[]@ pickupBlobs) +void FillAvailable(CBlob@ this, CBlob@[]@ available) { - for (uint i = 0; i < pickupBlobs.length; i++) + for (uint i = 0; i < pickup_netids.length; i++) { - CBlob @b = pickupBlobs[i]; + CBlob@ b = getBlobByNetworkID(pickup_netids[i]); + if (b is null || b is this) continue; - if (b !is this && canBlobBePickedUp(this, b)) + if (canBlobBePickedUp(this, b)) { available.push_back(b); } @@ -524,80 +486,74 @@ CBlob@ getClosestAimedBlob(CBlob@ this, CBlob@[] available) return closest; } - - CBlob@ getClosestBlob(CBlob@ this) { CBlob@ closest; CBlob@ target; // when hovering a blob - CBlob@[]@ pickupBlobs; - if (this.get("pickup blobs", @pickupBlobs)) - { - Vec2f pos = this.getPosition(); + Vec2f pos = this.getPosition(); - CBlob@[] available; - FillAvailable(this, available, pickupBlobs); + CBlob@[] available; + FillAvailable(this, available); - if (!isTapPickup(this)) + if (!isTapPickup(this)) + { + CBlob@ closestAimed = getClosestAimedBlob(this, available); + if (closestAimed !is null) { - CBlob@ closestAimed = getClosestAimedBlob(this, available); - if (closestAimed !is null) - { - return closestAimed; - } + return closestAimed; } + } - float closestScore = 999999.9f; - float drawOrderScore = -999999.9f; - for (uint i = 0; i < available.length; ++i) - { - CBlob @b = available[i]; + float closestScore = 999999.9f; + float drawOrderScore = -999999.9f; + for (uint i = 0; i < available.length; ++i) + { + CBlob@ b = available[i]; - Vec2f bpos = b.getPosition(); - // consider corpse center to be lower than it actually is because otherwise centers of player and corpse are on the same level, - // which makes corpse priority skyrocket if player is standing too close - if (b.hasTag("dead")) bpos += Vec2f(0, 6.0f); + Vec2f bpos = b.getPosition(); + // consider corpse center to be lower than it actually is because otherwise centers of player and corpse are on the same level, + // which makes corpse priority skyrocket if player is standing too close + if (b.hasTag("dead")) bpos += Vec2f(0, 6.0f); + Vec2f[]@ hoverShape; + bool isPointInsidePolygon = false; + + if (b.get("hover-poly", @hoverShape)) + { + isPointInsidePolygon = pointInsidePolygon(this.getAimPos(), hoverShape, bpos, b.isFacingLeft()); + } + + if (isPointInsidePolygon || b.isPointInside(this.getAimPos())) + { + // Let's just get the draw order of the sprite + CSprite@ bs = b.getSprite(); + float draworder = bs.getDrawOrder(); - Vec2f[]@ hoverShape; - bool isPointInsidePolygon = false; - - if (b.get("hover-poly", @hoverShape)) - { - isPointInsidePolygon = pointInsidePolygon(this.getAimPos(), hoverShape, bpos, b.isFacingLeft()); - } - - if (isPointInsidePolygon || b.isPointInside(this.getAimPos())) + if (draworder > drawOrderScore) { - // Let's just get the draw order of the sprite - CSprite @bs = b.getSprite(); - float draworder = bs.getDrawOrder(); - - if (draworder > drawOrderScore) - { - drawOrderScore = draworder; - @target = @b; - } - } + drawOrderScore = draworder; + @target = @b; + } + } - float maxDist = Maths::Max(this.getRadius() + b.getRadius() + 20.0f, 36.0f); + float maxDist = Maths::Max(this.getRadius() + b.getRadius() + 20.0f, 36.0f); - float dist = (bpos - pos).getLength(); - float factor = dist / maxDist; - float score = getPriorityPickupScale(this, b, factor); + float dist = (bpos - pos).getLength(); + float factor = dist / maxDist; + float score = getPriorityPickupScale(this, b, factor); - if (score < closestScore) - { - closestScore = score; - @closest = @b; - } + if (score < closestScore) + { + closestScore = score; + @closest = @b; } + } - if (closest !is null) { - @closest = @GetBetterAlternativePickupBlobs(available, closest); - } + if (closest !is null) + { + @closest = @GetBetterAlternativePickupBlobs(available, closest); } if (target !is null) @@ -609,55 +565,51 @@ CBlob@ getClosestBlob(CBlob@ this) bool canBlobBePickedUp(CBlob@ this, CBlob@ blob) { if (!blob.canBePickedUp(this)) return false; + + if (blob.isAttached() || blob.hasTag("no pickup")) return false; + + if (this.isOverlapping(blob)) return true; - float maxDist = Maths::Max(this.getRadius() + blob.getRadius() + 20.0f, 36.0f); - + const f32 maxDist = Maths::Max(this.getRadius() + blob.getRadius() + 20.0f, 36.0f); Vec2f pos = this.getPosition() + Vec2f(0.0f, -this.getRadius() * 0.9f); Vec2f pos2 = blob.getPosition(); + + const bool isInPickupRadius = (pos2 - pos).getLength() <= maxDist; + if (!isInPickupRadius) return false; Vec2f ray = pos2 - pos; - bool canRayCast = false; - - CMap@ map = getMap(); + bool canRayCast = true; HitInfo@[] hitInfos; - if(map.getHitInfosFromRay(pos, -ray.getAngle(), ray.Length(), this, hitInfos)) + if (getMap().getHitInfosFromRay(pos, -ray.getAngle(), ray.Length(), this, hitInfos)) { for (int i = 0; i < hitInfos.length; i++) { HitInfo@ hi = hitInfos[i]; CBlob@ b = hi.blob; - // collide with anything that isn't a platform - // could do proper platform direction check but probably not needed - if (b !is null && b !is this && b !is blob && b.isCollidable() && b.getShape().isStatic() && !b.isPlatform()) + // ray hit a tile + if (b is null) { canRayCast = false; break; - } - if(map.isTileSolid(hi.tile)) + if (b is blob) { - canRayCast = false; + canRayCast = true; break; } - // if our blob isn't in the list that means the ray stopped at a block - if (b is blob) + if (b !is this && b.isCollidable() && b.getShape().isStatic() && !b.isPlatform()) { - canRayCast = true; + canRayCast = false; + break; } } - - } else { - canRayCast = true; } - return (((pos2 - pos).getLength() <= maxDist) - && !blob.isAttached() && !blob.hasTag("no pickup") - && (canRayCast || this.isOverlapping(blob)) //overlapping fixes "in platform" issue - ); + return canRayCast; } void onInit(CSprite@ this) @@ -669,99 +621,72 @@ void onRender(CSprite@ this) { CBlob@ blob = this.getBlob(); - // render item held when in inventory if (blob.isKeyPressed(key_inventory)) { - CBlob @pickBlob = blob.getCarriedBlob(); - - if (pickBlob !is null) + CBlob@ carried = blob.getCarriedBlob(); + if (carried !is null) { - pickBlob.RenderForHUD((blob.getAimPos() + Vec2f(0.0f, 8.0f)) - blob.getPosition() , RenderStyle::normal); + carried.RenderForHUD((blob.getAimPos() + Vec2f(0.0f, 8.0f)) - blob.getPosition() , RenderStyle::normal); } } - if (blob.isKeyPressed(key_pickup)) - { - // pickup render - bool tickPlayed = false; - bool hover = false; - CBlob@[]@ pickupBlobs; - CBlob@[]@ closestBlobs; - blob.get("closest blobs", @closestBlobs); - CBlob@ closestBlob = null; - if (closestBlobs.length > 0) - { - @closestBlob = closestBlobs[0]; - } - - if (blob.get("pickup blobs", @pickupBlobs)) - { - // render outline only if hovering - for (uint i = 0; i < pickupBlobs.length; i++) - { - CBlob @b = pickupBlobs[i]; - - bool canBePicked = canBlobBePickedUp(blob, b); - - if (canBePicked) - { - b.RenderForHUD(RenderStyle::outline_front); - } + if (!blob.isKeyPressed(key_pickup)) return; - if (b is closestBlob) - { - hover = true; - Vec2f dimensions; - GUI::SetFont("menu"); - - /* - GUI::DrawCircle( - getDriver().getScreenPosFromWorldPos(b.getPosition()), - 32.0f, - SColor(255, 255, 255, 255) - ); - */ - - string invName = getTranslatedString(b.getInventoryName()); - GUI::GetTextDimensions(invName, dimensions); - GUI::DrawText(invName, getDriver().getScreenPosFromWorldPos(b.getPosition() - Vec2f(0, -b.getHeight() / 2)) - Vec2f(dimensions.x / 2, -8.0f), color_white); - - // draw mouse hover effect - //if (canBePicked) - { - b.RenderForHUD(RenderStyle::additive); - - if (!tickPlayed) - { - if (blob.get_u16("hover netid") != b.getNetworkID()) - { - Sound::Play(CFileMatcher("/select.ogg").getFirst()); - } + // pickup render + bool hover = false; - blob.set_u16("hover netid", b.getNetworkID()); - tickPlayed = true; - } + CBlob@ closest = null; + if (closest_netids.length > 0) + { + @closest = getBlobByNetworkID(closest_netids[0]); + } - //break; - } - } + // render outline only if hovering + for (uint i = 0; i < pickup_netids.length; i++) + { + CBlob@ b = getBlobByNetworkID(pickup_netids[i]); + if (b is null) continue; - } + if (canBlobBePickedUp(blob, b)) + { + b.RenderForHUD(RenderStyle::outline_front); + } - // no hover - if (!hover) + if (b is closest) + { + hover = true; + Vec2f dimensions; + GUI::SetFont("menu"); + + /* + GUI::DrawCircle( + getDriver().getScreenPosFromWorldPos(b.getPosition()), + 32.0f, + SColor(255, 255, 255, 255) + ); + */ + + string invName = getTranslatedString(b.getInventoryName()); + GUI::GetTextDimensions(invName, dimensions); + GUI::DrawText(invName, getDriver().getScreenPosFromWorldPos(b.getPosition() - Vec2f(0, -b.getHeight() / 2)) - Vec2f(dimensions.x / 2, -8.0f), color_white); + + // draw mouse hover effect + b.RenderForHUD(RenderStyle::additive); + + if (hover_netid != b.getNetworkID()) { - blob.set_u16("hover netid", 0); + Sound::Play(CFileMatcher("/select.ogg").getFirst()); } - // render outlines - - //for (uint i = 0; i < pickupBlobs.length; i++) - //{ - // pickupBlobs[i].RenderForHUD( RenderStyle::outline_front ); - //} + hover_netid = b.getNetworkID(); } } + + // no hover + if (!hover) + { + hover_netid = 0; + } } From d8e8168039e817a51a1c95052c0067c84c6e2915 Mon Sep 17 00:00:00 2001 From: Gingerbeard Date: Thu, 24 Oct 2024 01:17:10 -0400 Subject: [PATCH 2/3] [modified] pickup through platforms --- Entities/Common/Controls/StandardPickup.as | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Entities/Common/Controls/StandardPickup.as b/Entities/Common/Controls/StandardPickup.as index 2fd09b1ba..0c9ac2920 100644 --- a/Entities/Common/Controls/StandardPickup.as +++ b/Entities/Common/Controls/StandardPickup.as @@ -601,8 +601,20 @@ bool canBlobBePickedUp(CBlob@ this, CBlob@ blob) break; } - if (b !is this && b.isCollidable() && b.getShape().isStatic() && !b.isPlatform()) + if (b !is this && b.isCollidable() && b.getShape().isStatic()) { + if (b.isPlatform()) + { + ShapePlatformDirection@ plat = b.getShape().getPlatformDirection(0); + Vec2f dir = plat.direction; + if (!plat.ignore_rotations) dir.RotateBy(b.getAngleDegrees()); + + if (Maths::Abs(dir.AngleWith(ray)) < plat.angleLimit) + { + continue; + } + } + canRayCast = false; break; } From 2a8df36cf744de666690b0c3873099589aaf7019 Mon Sep 17 00:00:00 2001 From: Gingerbeard Date: Sat, 26 Oct 2024 00:15:51 -0400 Subject: [PATCH 3/3] [fixed] blobs getting thrown when not attached --- Entities/Common/Controls/StandardControls.as | 1 + 1 file changed, 1 insertion(+) diff --git a/Entities/Common/Controls/StandardControls.as b/Entities/Common/Controls/StandardControls.as index 0fac4d767..0b1f1d5ee 100755 --- a/Entities/Common/Controls/StandardControls.as +++ b/Entities/Common/Controls/StandardControls.as @@ -70,6 +70,7 @@ void onCommand(CBlob@ this, u8 cmd, CBitStream @params) if (pickedup.isAttached()) return; + pickedup.setPosition(caller.getPosition()); caller.server_Pickup(pickedup); } else if (cmd == this.getCommandID("detach"))