Author Topic: Detect if player is in liquid, and ALSO get the liquid object  (Read 808 times)

I need to do this as I'm assigning variables to different water bricks, and have the player be affected depending on those variables.

I've gotten this close, but it only seems to work on one half of the brick.
(this is on a static 4x4 grid (8x cubes))

Code: [Select]
package MiningLiquidPackage {
function PlayerStandardArmor::onEnterLiquid(%data,%obj,%coverage,%type) {
talk(%data SPC %obj SPC %coverage SPC %type);
%obj.schedule(100,doLiquidLoop);
return parent::onEnterLiquid(%data,%obj,%coverage,%type);
}
function PlayerStandardArmor::onLeaveLiquid(%data,%obj,%coverage,%type) {
cancel(%obj.liquidLoop);
talk(%data SPC %obj SPC %coverage SPC %type);
return parent::onLeaveLiquid(%data,%obj,%coverage,%type);
}
};
activatePackage(MiningLiquidPackage);

function Player::doLiquidLoop(%this) {
cancel(%this.liquidLoop);
%this.liquidLoop = %this.schedule(500,doLiquidLoop);

%player_pos = %this.getPosition();
%player_pos[x] = getWord(%player_pos,0);
%player_pos[y] = getWord(%player_pos,1);
%player_pos[z] = getWord(%player_pos,2);

// ugh
// can't %array[%another[1]] and it SUCKS
if(%player_pos[x] < 0) {
%player_pos_xf = mCeil(%player_pos[x] - (%player_pos[x] % 4));
} else {
%player_pos_xf = mFloor(%player_pos[x] - (%player_pos[x] % 4));
}
if(%player_pos[y] < 0) {
%player_pos_yf = mCeil(%player_pos[y] - (%player_pos[y] % 4));
} else {
%player_pos_yf = mFloor(%player_pos[y] - (%player_pos[y] % 4));
}
if(%player_pos[z] < 0) {
%player_pos_zf = mCeil(%player_pos[z] - (%player_pos[z] % 4));
} else {
%player_pos_zf = mFloor(%player_pos[z] - (%player_pos[z] % 4));
}

%brick = $Mining::Brick[%player_pos_xf,%player_pos_yf,%player_pos_zf];

if(!isObject(%brick)) {
talk("NOT OBJECT" SPC %brick SPC "$Mining::Brick[" @ %player_pos_xf @ "," @ %player_pos_yf @ "," @ %player_pos_zf @ "]" SPC %this.getPosition());
return;
}

%brick_box = %brick.getWorldBox();
%brick_box[x1] = getWord(%brick_box,0);
%brick_box[y1] = getWord(%brick_box,1);
%brick_box[z1] = getWord(%brick_box,2);
%brick_box[x2] = getWord(%brick_box,3);
%brick_box[y2] = getWord(%brick_box,4);
%brick_box[z2] = getWord(%brick_box,5);

if(%player_pos_xf >= %brick_box[x1] && %player_pos_yf >= %brick_box[y1] && %player_pos_zf >= %brick_box[z1] && %player_pos_xf <= %brick_box[x2] && %player_pos_yf <= %brick_box[y2] && %player_pos_zf <= %brick_box[z2]) {
if(%brick.liquidObj != -1) {
talk("IN" SPC %brick SPC "$Mining::Brick[" @ %player_pos_xf @ "," @ %player_pos_yf @ "," @ %player_pos_zf @ "]" SPC %this.getPosition());
} else {
talk("NOT LIQUID" SPC "$Mining::Brick[" @ %player_pos_xf @ "," @ %player_pos_yf @ "," @ %player_pos_zf @ "]" SPC %this.getPosition());
}
}
}

I've been at this for hours now and I'm tearing out my hair over this.
It'd be nice if y'know, the onEnter/LeaveLiquid would actually return the object, but nah, of course it doesn't.

EDIT: sorry for the formatting, PHP got habitual
« Last Edit: February 09, 2015, 02:12:26 AM by TheBlackParrot »

It's entirely possible for a player to be in more than one liquid object.  The best solution would probably be to call a containerBoxSearch at the player's world box, adjusting for the bizarre skew on the vertical axis for Player::getWorldBox.

Code: [Select]
initContainerBoxSearch(%boxCenter, %boxSize, %searchMask);   // In this case, %searchMask would be $Typemasks::PhysicalZoneObject
while(isObject(%obj = containerSearchNext()))
{
    // Run code on the zero or more physical zones in question
}

EDIT: I've just checked, and apparently the physical zones created by the default water bricks do not have pointers to the bricks themselves.  If you absolutely need the bricks, then I'm not sure how best to help you, because checking for the bricks themselves will miss things like environmental liquids.  On a related note, I just double-checked and %array[%in[%an[%array]]]; absolutely works.  Even if it didn't, TorqueScript just appends the array indexer to the end of the variable name, so you could do %array[%in @ %an @ %array]; and get exactly the same results.  (EDIT 2: That's not quite right, but that's what I get for trying to code at 5 in the morning.)
« Last Edit: February 09, 2015, 04:52:25 AM by Xalos »

Isn't there some isSwimming check that you can do?

I could have sworn..

Isn't there some isSwimming check that you can do?

I could have sworn..
Look at his code. He already knows how to check if they're in water.

It's entirely possible for a player to be in more than one liquid object.  The best solution would probably be to call a containerBoxSearch at the player's world box, adjusting for the bizarre skew on the vertical axis for Player::getWorldBox.

Code: [Select]
initContainerBoxSearch(%boxCenter, %boxSize, %searchMask);   // In this case, %searchMask would be $Typemasks::PhysicalZoneObject
while(isObject(%obj = containerSearchNext()))
{
    // Run code on the zero or more physical zones in question
}

EDIT: I've just checked, and apparently the physical zones created by the default water bricks do not have pointers to the bricks themselves.  If you absolutely need the bricks, then I'm not sure how best to help you, because checking for the bricks themselves will miss things like environmental liquids.  On a related note, I just double-checked and %array[%in[%an[%array]]]; absolutely works.  Even if it didn't, TorqueScript just appends the array indexer to the end of the variable name, so you could do %array[%in @ %an @ %array]; and get exactly the same results.  (EDIT 2: That's not quite right, but that's what I get for trying to code at 5 in the morning.)
I'll try that out later today.
I'm having to manually create the zone as well, I could always add in a variable in the zone pointing back to the brick upon its creation. (don't really need environmental liquids for this)

I'll try that out later today.
I'm having to manually create the zone as well, I could always add in a variable in the zone pointing back to the brick upon its creation. (don't really need environmental liquids for this)
I'm pretty sure that the default water brick zones already have a variable linking to the brick on them.

I'm pretty sure that the default water brick zones already have a variable linking to the brick on them.

EDIT: I've just checked, and apparently the physical zones created by the default water bricks do not have pointers to the bricks themselves.

Code: [Select]
function Player::doLiquidLoop(%this) {
cancel(%this.liquidLoop);
%this.liquidLoop = %this.schedule(500,doLiquidLoop);

initContainerBoxSearch(%this.getPosition(), "0.1 0.1 0.1", $TypeMasks::FXBrickObjectType);
while((%targetObject = containerSearchNext()) != 0 && isObject(%targetObject)) {
if(%targetObject.liquidObj != -1) {
talk("IN" SPC %targetObject);
}
}
}

This appears to be working fine, thanks for the help guys.
I couldn't get the search to work for zones, but since I'm applying a "liquid object" variable (scriptObject containing variables relating to the type of liquid), this should do the trick.

Try $TypeMasks::WaterObjectType?
If not try $TypeMasks::PhysicalZoneObjectType.
If that one isn't it then you could try $TypeMasks::EnvironmentObjectType.