Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Port

Pages: 1 ... 7 8 9 10 11 [12]
166
Modification Help / Pathfinding (A*)
« on: November 19, 2011, 06:31:29 AM »
I'm attempting to create an implementation of the A* pathfinding algorithm in TorqueScript with pre-calculated node neighbors. I have neighbor detection working, but the actual pathfinding simply isn't working (returning "").

Any help would be greatly appreciated.
Code: [Select]
function findPath( %nodes, %start, %goal )
{
%closedset = listObject();
%openset = listObject(); %openset.fillWords( %nodes );
%came_from = dictObject();

%g_score[ %start ] = 0;
%h_score[ %start ] = path_dist( %start, %goal );
%f_score[ %start ] = %g_score[ %start ] + %h_score[ %start ];

while ( %cnt = %openset.size() )
{
%x = -1;

for ( %i = 0 ; %i < %cnt ; %i++ )
{
%obj = %openset.get( %i );
%val = ( strLen( %val = %f_score[ %obj ] ) ? %val : 0 );
if ( !strLen( %min ) || %val < %min )
{
%min = %val;
%x = %obj;
}
}

if ( %x == %goal )
{
%rec = reconstruct_path( %came_from, %came_from.get( %goal ) );
%came_from.delete();
%openset.delete();
%closedset.delete();

return %rec;
}

%openset.remove( %x );
%closedset.add( %x );

%nbrs = neighbor_nodes( %x );
%cnt = getWordCount( %nbrs );

if ( strLen( %nbrs ) && %cnt > 0 ) for ( %i = 0 ; %i < %cnt ; %i++ )
{
%y = getWord( %nbrs, %i );

if ( %closedset.has( %y ) )
continue;

%tentative_g_score = %g_score[ %x ] + path_dist( %x, %y );

if ( !%openset.has( %y ) )
{
%openset.add( %y );
%tentative_is_better = true;
}
else if ( %tentative_g_score < %g_score[ %y ] )
%tentative_is_better = true;
else
%tentative_is_better = false;

if ( %tentative_is_better )
{
%came_from.set( %y, %x );
%g_score[ %y ] = %tentative_g_score;
%h_score[ %y ] = path_dist( %y, %goal );
%f_score[ %y ] = %g_score[ %y ] + %h_score[ %y ];
}
}
}

%closedset.delete();
%openset.delete();
%came_from.delete();

return "failure";
}

// function A*(start,goal)
//     closedset := the empty set    // The set of nodes already evaluated.
//     openset := {start}    // The set of tentative nodes to be evaluated, initially containing the start node
//     came_from := the empty map    // The map of navigated nodes.
//
//     g_score[start] := 0    // Cost from start along best known path.
//     h_score[start] := heuristic_cost_estimate(start, goal)
//     f_score[start] := g_score[start] + h_score[start]    // Estimated total cost from start to goal through y.
//
//     while openset is not empty
//         x := the node in openset having the lowest f_score[] value
//         if x = goal
//             return reconstruct_path(came_from, came_from[goal])
//
//         remove x from openset
//         add x to closedset
//         foreach y in neighbor_nodes(x)
//             if y in closedset
//                 continue
//             tentative_g_score := g_score[x] + dist_between(x,y)
//
//             if y not in openset
//                 add y to openset
//                 tentative_is_better := true
//             else if tentative_g_score < g_score[y]
//                 tentative_is_better := true
//             else
//                 tentative_is_better := false
//
//             if tentative_is_better = true
//                 came_from[y] := x
//                 g_score[y] := tentative_g_score
//                 h_score[y] := heuristic_cost_estimate(y, goal)
//                 f_score[y] := g_score[y] + h_score[y]
//
//     return failure

function reconstruct_path( %came_from, %current_node )
{
if ( %came_from.has( %current_node ) )
{
%p = reconstruct_path( %came_from, %came_from.get( %current_node ) );
return %p SPC %current_node;
}
else
return %current_node;
}
// function reconstruct_path(came_from, current_node)
//     if came_from[current_node] is set
//         p = reconstruct_path(came_from, came_from[current_node])
//         return (p + current_node)
//     else
//         return current_node

function path_dist( %a, %b )
{
return mAbs( vectorDist( %a.position, %b.position ) );
}

function neighbor_nodes( %a )
{
return %a.connections;
}

datablock fxDTSBrickData( brickNodeData : brick2x2fData )
{
category = "Special";
subCategory = "Interactive";
uiName = "Node Brick";

isNodeBrick = true;
};

function nodeGroupSG::findPath( %this, %start, %end )
{
return findPath( %this.getNodes(), %start, %end );
}

function nodeGroupSG::getNodes( %this )
{
%cnt = %this.getCount();
%str = "";

for ( %i = 0 ; %i < %cnt ; %i++ )
%str = %str @ ( strLen( %str ) ? " " : "" ) @ %this.getObject( %i );

return %str;
}

function nodeCanSee( %obj, %col )
{
%start = %obj.position;
%end = %col.position;
%mask = $TypeMasks::All;
%avoid = %obj.brick;

%ray = containerRayCast( %start, %end, %mask, %avoid );
return ( %col.brick == objFromRayCast( %ray ) );
}

function scriptObject::updateConns( %this )
{
%this.connections = "";
%cnt = %this.getGroup().getCount();

for ( %i = 0 ; %i < %cnt ; %i++ )
{
%col = %this.getGroup().getObject( %i );

if ( %col == %this )
continue;

if ( nodeCanSee( %this, %col ) )
{
%this.connections = %this.connections @ ( strLen( %this.connections ) ? " " : "" ) @ %col;
if ( !isEventPending( %col.brick.restoreRender ) )
{
%col.brick.setRendering( 1 );
%col.brick.restoreRender = %col.brick.schedule( 1000, setRendering, 0 );
%col.schedule( 100, updateConns );
}
}
}
}

package pathfinding_package
{
function fxDTSBrick::onPlant( %this )
{
parent::onPlant( %this );

if ( %this.isPlanted && %this.getDataBlock().isNodeBrick
&& !isObject( %this.nodeObj )
&& isObject( %bg = %this.getGroup() ) )
{
%this.nodeObj = new scriptObject()
{
brick = %this;
position = %this.getPosition();
numConnections = 0;
};

if ( !isObject( %ng = %bg.nodeGroup ) )
{
%ng = %bg.nodeGroup = new scriptGroup()
{
class = "nodeGroupSG";

brickGroup = %bg;
client = %this.client;

name = %bg.name;
bl_id = %bg.bl_id;
};
}

%ng.add( %this.nodeObj );
%this.nodeObj.schedule( 500, updateConns );

%this.setRendering( false );
%this.setColliding( false );
%this.setRayCasting( true );
}
}

function fxDTSBrick::onLoadPlant( %this )
{
parent::onLoadPlant( %this );

if ( %this.isPlanted && %this.getDataBlock().isNodeBrick
&& !isObject( %this.nodeObj )
&& isObject( %bg = %this.getGroup() ) )
{
%this.nodeObj = new scriptObject()
{
brick = %this;
position = %this.getPosition();
numConnections = 0;
};

if ( !isObject( %ng = %bg.nodeGroup ) )
{
%ng = %bg.nodeGroup = new scriptGroup()
{
class = "nodeGroupSG";

brickGroup = %bg;
client = %this.client;

name = %bg.name;
bl_id = %bg.bl_id;
};
}

%ng.add( %this.nodeObj );
%this.nodeObj.schedule( 500, updateConns );

%this.setRendering( false );
%this.setColliding( false );
%this.setRayCasting( true );
}
}

function fxDTSBrick::onRemove( %this )
{
if ( isObject( %obj = %this.nodeObj ) )
%obj.delete();

parent::onRemove( %this );
}
};
activatePackage( pathfinding_package );

167
Modification Help / findClients( mask ) [RESOURCE]
« on: November 15, 2011, 08:34:42 AM »
When scripting, I often find myself in the situation that findClientByName or findClientByBL_ID aren't good enough, and I need to expose a better way of selecting targets to clients. So this time, I decided to make my own method.

findClients( mask )
    return: string


The return value will always be a string. If no targets are found, this is simply an empty string. If targets are found, it will be a space-seperated list of object ID's (of gameConnection objects).

mask is a string containing a "search pattern" which is highly inspired by SourceMod. Normally, it will simply return all clients whose names mask occurs in, but these "special rules" occur:
  • If mask starts with an exclamation mark (!), it will return all clients who do not match the expression. Example: !pie will return all clients that do not have pie in their name.
  • If mask starts with the & character, it will return the client with the specified user ID. Example: &2 will return the third player on the server (because user ID's start at 0).
  • If mask starts with a sharp (#) which is followed by a number, it will return all clients using the specified BL_ID. Example: #12297 will return all clients with BL_ID 12297. (Note: On LAN servers, there are no BL_IDs, all clients play under BL_ID 999999)
  • If mask starts with a sharp (#) which is followed by a string, it will return all clients with the exact name specified. Example: #Port will return all clients with the name "Port", but not clients with the name "Portable".
  • If mask starts with the at character (@), it will return a special list of clients matching the "tag" following it. A list of all tags can be seen below.

List of available "tags" for @:
  • all: All clients.
  • alive: All clients with a player object that is not dead.
  • admin: All admins.
  • admins: All admins.
  • sa: All super admins.
  • sas: All super admins.
  • superadmin: All super admins.
  • superadmins: All super admins.
  • loading: All clients who are currently loading.

Please note:
  • You cannot combine ! and a diffirent operator in a incorrect way. Example: @!loading will return all clients. The correct use would be !@loading, to return all clients who are not loading. Another example: #!Port will return all clients named exactly "!Port". To return all clients who are not named "Port", you need to use !#Port.
  • Specifying none or an invalid "tag" to @ will just result in retrieving all clients.


Code: (Example of usage) [Select]
exec( "./Support_ClientFind.cs" );

function serverCmdAdvKick( %cl, %a, %b, %c, %d, %e )
{
if ( !%cl.isAdmin )
return;

%result = findClients( trim( %a SPC %b SPC %c SPC %d SPC %e ) );

if ( !strLen( %result ) || !getWordCount( %result ) )
return;

%cnt = getWordCount( %result );
for ( %i = 0 ; %i < %cnt ; %i++ )
{
%target = getWord( %result, %i );
messageAll( '', "\c3" @ %cl.name SPC "\c6has kicked \c3" @ %target.getPlayerName() );
%target.delete();
}
}

With the above code, typing /advkick !@loading would kick all players who are not currently loading.

Download: http://pastebin.com/raw.php?i=KtE3pRLQ
(included functions: findClients, startsWith, clientFind_isInt)

If you find any bugs or have suggestions for features, feel free to tell me.

168
Gallery / Borg TDM
« on: November 06, 2011, 01:12:20 AM »
Felt like I should post this here already.
I already made something quite a bit like this, which I'm actually hosting right now (Port's Borg TDM).
I'll just explain the rules of the game-mode here so I won't have to explain it over and over on the server:

There are two "teams", the Blockheads and the Borg.
The Blockheads can use weapons, move at normal speed and can only damage themself and the Borg.
The Borgs cannot use weapons, move at a faster speed and can turn Blockheads into Borgs by right-clicking them.
The Blockheads' goal is to kill all Borgs, and the Borgs' goal is to turn everyone into Borgs.

There are no visual diffirences between a Blockhead and a Borg, but Borgs can be spotted by that they are not holding a weapon and move rather fast.

Blockheads should use a searching behaviour, once in a while checking behind their back.
Borgs should use a stealthy behaviour, often taking alternative routes.

I'll be hosting this regularily, EU server.





169
Modification Help / Sit while moving
« on: November 03, 2011, 12:36:14 AM »
(server-sided)
Is there a way to force a player to sit down -- and even if they move, they'll still be sitting down?

I've tried some stuff using .setActionThread("sit", 1) which seems to be cancelled when the player moves. I've also tried looping that function but that will only cause them to sit down when they finish moving.

I've also tried to apply it to AIPlayers, but it is cancelled when they move as well.

Pages: 1 ... 7 8 9 10 11 [12]