Results 1 to 8 of 8

Thread: Spawnable Triggers

  1. #1
    Global Mossaderator Mitch's Avatar
    Join Date
    Nov 2012
    Posts
    654
    Thanks
    204
    Thanked 450 Times in 305 Posts

    Spawnable Triggers

    Originally posted by general sniperfire on IWNation.
    https://web.archive.org/web/20110107...y-4-scripting/

    CoD4
    PHP Code:
    /*
    ////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////

        Sniper[+]FIRE>>> Spawnable triggers script v1.0


    To spawn a trigger:

        1. Build an array of 6 values. The first set of three
        defines one corner of the trigger. The second three
        define the opposite corner.

        2. Call spawnTrigger(), and pass in the array. an optional
        parameter is type, which determines the type of trigger.
        See extra settings. A new trigger entity is returned.

        Ex:
            trigger = spawnTrigger( volume_array, "multiple");
        This would spawn a trigger_multiple.


    To monitor a trigger:

        Simply use:
            trigger waittill("trigger", player);
        This will only work on players.
        The player variable is optional.

        Also, you can check to see if an entity is touching it with:
            if( player isTouchingTrigger(trigger) )


    Extra settings:

        Types of triggers supported:
            |- multiple
            |- use*
            |- hurt

        * - use triggers do not yet have icons that appear when able
            to be pushed.

        .delay - delay between triggering. Default: 0.05
        .dmg - dmg to do for hurt triggers. Default: 5
        ._color - used in debug to change line color.


            -==Debug==-

            When developer_script is enabled and the "debugtriggers" dvar is set,
        boxes will be drawn around triggers to help determine the position.
        use ._color to change the color.


    ***Notes:

        1. Only rectangular prism shaped triggers will be made, with no rotation.
        2. Waittill("trigger") method only registers players. You can check to see
            if other entities are touching the trigger by: if( entity isTouchingTrigger(trigger) )


    ////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////
    */

    spawnTrigger(volumetype)
    {
        
    trigger spawnstruct();

        
    trigger.volume volume;

        if(
    isdefined(type))
            
    trigger.type type;
        else
            
    trigger.type "multiple";

        if(
    type == "hurt")
            
    trigger.dmg 5;

        
    trigger.delay 0;

        
    trigger thread watchTrigger();

        return 
    trigger;
    }

    watchTrigger()
    {
        for(;;)
        {
            for(
    i=0;i<level.players.size;i++)
            {
                
    player level.players[i];
                if(
    player.sessionstate != "playing")
                    continue;

                if(
    player isInVolume(self.volume))
                {
                    if(
    self.type == "hurt")
                        
    player maps\mp\gametypes\_callbacksetup::CodeCallback_PlayerDamage(selfundefinedself.dmg0"MOD_TRIGGER_HURT""none"player.origin, (0,0,0), "none"0);
                    else if(
    self.type == "use" && !player usebuttonPressed())
                        continue;

                    
    self notify("trigger"player);

                    if(
    self.delay 0)
                        
    wait(self.delay);
                }

            }

            
    wait(0.05);
            
    debugTrigger(self.volume);
        }
    }

    isTouchingTrigger(trigger)
    {
        return 
    self isInVolume(trigger.volume);
    }

    isInVolume(volume)
    {
        
    max[0] = getVmax(volume0);
        
    max[1] = getVmax(volume1);
        
    max[2] = getVmax(volume2);
        
    min[0] = getVmin(volume0);
        
    min[1] = getVmin(volume1);
        
    min[2] = getVmin(volume2);

        for(
    axis=0;axis<3;axis++)
        {
            if(
    self.origin[axis] < min[axis] || self.origin[axis] > max[axis])
                return 
    false;
        }
        return 
    true;
    }

    getVmax(pointsaxis)
    {
        
    max undefined;

        for(
    i=0;i<points.size;i+=3)
        {
            if(!
    isdefined(max) || points[i+axis] > max)
            {
                
    max points[i+axis];
            }
        }

        return 
    max;
    }

    getVmin(pointsaxis)
    {
        
    min undefined;

        for(
    i=0;i<points.size;i+=3)
        {
            if(!
    isdefined(min) || points[i+axis] < min)
            {
                
    min points[i+axis];
            }
        }

        return 
    min;
    }

    debugTrigger(volume)
    {
    /
    #
        
    if( getdvar("debugTriggers") == "")
            return;

        if(!
    isdefined(self._color))
            
    self._color = (1,1,1);

        
    max[0] = getVmax(volume0);
        
    max[1] = getVmax(volume1);
        
    max[2] = getVmax(volume2);
        
    min[0] = getVmin(volume0);
        
    min[1] = getVmin(volume1);
        
    min[2] = getVmin(volume2);

        
    line( (max[0], max[1], max[2]), (min[0], max[1], max[2]), self._color);
        
    line( (max[0], max[1], max[2]), (max[0], min[1], max[2]), self._color);
        
    line( (max[0], max[1], max[2]), (max[0], max[1], min[2]), self._color);

        
    line( (min[0], min[1], max[2]), (min[0], max[1], max[2]), self._color);
        
    line( (min[0], min[1], max[2]), (max[0], min[1], max[2]), self._color);
        
    line( (min[0], min[1], max[2]), (min[0], min[1], min[2]), self._color);

        
    line( (max[0], min[1], min[2]), (max[0], max[1], min[2]), self._color);
        
    line( (max[0], min[1], min[2]), (min[0], min[1], min[2]), self._color);
        
    line( (max[0], min[1], min[2]), (max[0], min[1], max[2]), self._color);

        
    line( (min[0], max[1], min[2]), (max[0], max[1], min[2]), self._color);
        
    line( (min[0], max[1], min[2]), (min[0], max[1], max[2]), self._color);
        
    line( (min[0], max[1], min[2]), (min[0], min[1], min[2]), self._color);
    #/

    CoD2
    PHP Code:
    /*
    ////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////

        Sniper[+]FIRE>>> Spawnable triggers script v1.0


    To spawn a trigger:

        1. Build an array of 6 values. The first set of three
        defines one corner of the trigger. The second three
        define the opposite corner.

        2. Call spawnTrigger(), and pass in the array. an optional
        parameter is type, which determines the type of trigger.
        See extra settings. A new trigger entity is returned.

        Ex:
            trigger = spawnTrigger( volume_array, "multiple");
        This would spawn a trigger_multiple.


    To monitor a trigger:

        Simply use:
            trigger waittill("trigger", player);
        This will only work on players.
        The player variable is optional.

        Also, you can check to see if an entity is touching it with:
            if( player isTouchingTrigger(trigger) )


    Extra settings:

        Types of triggers supported:
            |- multiple
            |- use*
            |- hurt

        * - use triggers do not yet have icons that appear when able
            to be pushed.

        .delay - delay between triggering. Default: 0.05
        .dmg - dmg to do for hurt triggers. Default: 5
        ._color - used in debug to change line color.


            -==Debug==-

            When developer_script is enabled and the "debugtriggers" dvar is set,
        boxes will be drawn around triggers to help determine the position.
        use ._color to change the color.


    ***Notes:

        1. Only rectangular prism shaped triggers will be made, with no rotation.
        2. Waittill("trigger") method only registers players. You can check to see
            if other entities are touching the trigger by: if( entity isTouchingTrigger(trigger) )


    ////////////////////////////////////////////////////////////////
    ////////////////////////////////////////////////////////////////
    */

    spawnTrigger(volumetype)
    {
        
    trigger spawnstruct();

        
    trigger.volume volume;

        if(
    isdefined(type))
            
    trigger.type type;
        else
            
    trigger.type "multiple";

        if(
    type == "hurt")
            
    trigger.dmg 5;

        
    trigger.delay 0;

        
    trigger thread watchTrigger();

        return 
    trigger;
    }

    watchTrigger()
    {
        for(;;)
        {
            
    players getentarray("player""classname");

            for(
    i=0;i<players.size;i++)
            {
                
    player players[i];

                if(!
    isPlayer(player) || player.sessionstate != "playing")
                    continue;

                if(
    player isInVolume(self.volume))
                {
                    if(
    self.type == "hurt")
                        
    player maps\mp\gametypes\_callbacksetup::CodeCallback_PlayerDamage(selfselfself.dmg0"MOD_TRIGGER_HURT""none"player.origin, (0,0,0), "none"0);
                    else if(
    self.type == "use" && !player usebuttonPressed())
                        continue;

                    
    self notify("trigger"player);

                    if(
    self.delay 0)
                        
    wait(self.delay);
                }

            }

            
    wait(0.05);
            
    debugTrigger(self.volume);
        }
    }

    isTouchingTrigger(trigger)
    {
        return 
    self isInVolume(trigger.volume);
    }

    isInVolume(volume)
    {
        
    max[0] = getVmax(volume0);
        
    max[1] = getVmax(volume1);
        
    max[2] = getVmax(volume2);
        
    min[0] = getVmin(volume0);
        
    min[1] = getVmin(volume1);
        
    min[2] = getVmin(volume2);

        for(
    axis=0;axis<3;axis++)
        {
            if(
    self.origin[axis] < min[axis] || self.origin[axis] > max[axis])
                return 
    false;
        }
        return 
    true;
    }

    getVmax(pointsaxis)
    {
        
    max undefined;

        for(
    i=0;i<points.size;i+=3)
        {
            if(!
    isdefined(max) || points[i+axis] > max)
            {
                
    max points[i+axis];
            }
        }

        return 
    max;
    }

    getVmin(pointsaxis)
    {
        
    min undefined;

        for(
    i=0;i<points.size;i+=3)
        {
            if(!
    isdefined(min) || points[i+axis] < min)
            {
                
    min points[i+axis];
            }
        }

        return 
    min;
    }

    debugTrigger(volume)
    {
        if( 
    getcvar("debugTriggers") == "")
            return;

        if(!
    isdefined(self._color))
            
    self._color = (1,1,1);

        
    max[0] = getVmax(volume0);
        
    max[1] = getVmax(volume1);
        
    max[2] = getVmax(volume2);
        
    min[0] = getVmin(volume0);
        
    min[1] = getVmin(volume1);
        
    min[2] = getVmin(volume2);

        
    line( (max[0], max[1], max[2]), (min[0], max[1], max[2]), self._color);
        
    line( (max[0], max[1], max[2]), (max[0], min[1], max[2]), self._color);
        
    line( (max[0], max[1], max[2]), (max[0], max[1], min[2]), self._color);

        
    line( (min[0], min[1], max[2]), (min[0], max[1], max[2]), self._color);
        
    line( (min[0], min[1], max[2]), (max[0], min[1], max[2]), self._color);
        
    line( (min[0], min[1], max[2]), (min[0], min[1], min[2]), self._color);

        
    line( (max[0], min[1], min[2]), (max[0], max[1], min[2]), self._color);
        
    line( (max[0], min[1], min[2]), (min[0], min[1], min[2]), self._color);
        
    line( (max[0], min[1], min[2]), (max[0], min[1], max[2]), self._color);

        
    line( (min[0], max[1], min[2]), (max[0], max[1], min[2]), self._color);
        
    line( (min[0], max[1], min[2]), (min[0], max[1], max[2]), self._color);
        
    line( (min[0], max[1], min[2]), (min[0], min[1], min[2]), self._color);

    Example
    PHP Code:
    volume = [];
    volume[0] = 2080// min (x)
    volume[1] = 197// min (y)
    volume[2] = 336// min  (z)
    volume[3] = 2672// max  (x)
    volume[4] = 254// max  (y)
    volume[5] = 436// max  (z)

    trigger sim\_sf_triggers::spawnTrigger(  volume"hurt");
    trigger._color = (1,0,0);
    trigger.dmg 1000
    Result: http://screenshot.xfire.com/s/105753647-4.jpg

    Click image for larger version. 

Name:	box trigger.jpg 
Views:	151 
Size:	200.1 KB 
ID:	807

    (The debug lines are only visible when 'dedicated' is 0 and 'developer', 'developer_script' and 'debugTriggers' are set to 1)

  2. The Following 2 Users Say Thank You to Mitch For This Useful Post:

    kung foo man (5th December 2014),maxdamage99 (29th April 2016)

  3. #2
    Brigadier General
    Join Date
    Dec 2012
    Posts
    1,012
    Thanks
    440
    Thanked 171 Times in 132 Posts
    What is so special about this? We already were able to spawn triggers with a corresponding action? Am I missing something?

  4. #3
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    This doesnt do much special stuff indeed, just a check for isinside(cube coordinates) would suffice for this to work...
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  5. #4
    Brigadier General
    Join Date
    Oct 2012
    Posts
    994
    Thanks
    20
    Thanked 588 Times in 388 Posts
    Quote Originally Posted by Ni3ls View Post
    What is so special about this? We already were able to spawn triggers with a corresponding action? Am I missing something?
    No, you aren't missing anything. All it does is some less-than clever distance checks. You can do exactly the same with a simple 2D distance check between the player and a script_origin. If it returns true, you know the player is "touching" the entity; if it returns false, you know the player isn't touching. Lots of checks on origins is completely unnecessary.

    EDIT - I remember when this was first posted, a lot of us expressed the view that it was not a very efficient way to do things, but SniperFire said he wanted something which would return isTouching(). I and others told him you could do that on a trigger_radius, and he replied that he didn't know about the isTouching() function on trigger_radius, so it looked like all this work was pretty redundant anyway.
    Last edited by Tally; 4th December 2014 at 19:50.

  6. #5
    Assadministrator kung foo man's Avatar
    Join Date
    Jun 2012
    Location
    trailerpark
    Posts
    2,010
    Thanks
    2,102
    Thanked 1,084 Times in 753 Posts
    Well, normal spawnable triggers are spheres only and this is box + debug lines, which are kinda helpful.
    timescale 0.01

  7. #6
    Brigadier General
    Join Date
    Oct 2012
    Posts
    994
    Thanks
    20
    Thanked 588 Times in 388 Posts
    Quote Originally Posted by kung foo man View Post
    Well, normal spawnable triggers are spheres only and this is box + debug lines, which are kinda helpful.
    But it's the efficiency of the code that is questionable. It can all be done so much simpler and just as effectively, without putting such a strain on the server. This is my universal trigger function for COD1, which doesn't natively support triggers which can be delimited by radius (there is no trigger_radius in COD1 - only trigger_multiple can be spawned dynamically):

    Code:
    spawnTrigger( origin, radius )
    {
    	ent = spawn( "script_origin", origin );
    	ent.origin = origin;
    	ent.touchingPlayer = [];
    	ent.touchingRadius = radius;
    	ent thread flag_touching();
    	
    	return( ent );
    }
    
    flag_touching()
    {
    	level endon( "intermission" );
    	
    	/#
    	showBoundedArea( self, (1,0,0) );
    	#/
    
    	for( ;; )
    	{
    		players = getEntArray( "player", "classname" );
    			
    		for( i=0; i < players.size; i++ )
    		{
    			player = players[i];
    			
    			if( isPlayer( player ) && isAlive( player ) && player.sessionstate == "playing" )
    			{	
    				if( distance( self.origin, player.origin ) < self.touchingRadius )
    				{
    					self notify( "trigger", player );
    				}
    			}
    		}
    		
    		wait( 0.05 );
    	}
    }
    
    
    showBoundedArea( trigger, color )
    {
    	player_height = 80.0;
    	center = trigger.origin;
    	forward = anglestoforward( trigger.angles );
    	right = anglestoright( trigger.angles );
    
    	forward = maps\mp\_utility::vectorScale( forward, trigger.touchingRadius );
    	right = maps\mp\_utility::vectorScale( right, trigger.touchingRadius );
    
    	a = center + forward - right;
    	b = center + forward + right;
    	c = center - forward + right;
    	d = center - forward - right;
    	
    	thread lineUntilNotified( a, b, color, 0 );
    	thread lineUntilNotified( b, c, color, 0 );
    	thread lineUntilNotified( c, d, color, 0 );
    	thread lineUntilNotified( d, a, color, 0 );
    
    	thread lineUntilNotified( a, a + (0, 0, player_height), color, 0 );
    	thread lineUntilNotified( b, b + (0, 0, player_height), color, 0 );
    	thread lineUntilNotified( c, c + (0, 0, player_height), color, 0 );
    	thread lineUntilNotified( d, d + (0, 0, player_height), color, 0 );
    
    	a = a + ( 0, 0, player_height );
    	b = b + ( 0, 0, player_height );
    	c = c + ( 0, 0, player_height );
    	d = d + ( 0, 0, player_height );
    	
    	thread lineUntilNotified( a, b, color, 0 );
    	thread lineUntilNotified( b, c, color, 0 );
    	thread lineUntilNotified( c, d, color, 0 );
    	thread lineUntilNotified( d, a, color, 0 );
    	
    }
    
    lineUntilNotified( start, end, color, depthTest )
    {	
    	for( ;; )
    	{
    		line( start, end, color, depthTest );
    		wait( 0.05 );
    	}
    }
    And the developer mode produces this marked bounded area:



    In the gametype files, you code it as if it were a trigger_radius. This is my trigger think for CTF for COD1:

    Code:
    flag_think()
    {
    	level endon( "intermission" );
    	
    	objective_add( self.objective, "current", self.origin, self.compassflag );
    
    	for( ;; )
    	{
    		self waittill( "trigger", player );
    			
    		if( isPlayer( player ) && isAlive( player ) && player.sessionstate == "playing" )
    		{	
    			// PICKUP THE FLAG !!
    			if( player.pers["team"] != self.team )
    			{
    				if( self.atbase )
    				{
    					if( player.pers["team"] == "allies" )
    						player AnnouncetoAll( &"CTF_STOLE_AXIS", player.name );
    					else
    						player AnnouncetoAll( &"CTF_STOLE_ALLIES", player.name );
    					
    					thread logEvent( "ctf_pickedup_flag", player );
    				}
    				else
    				{
    					if( player.pers["team"] == "allies" )
    						player AnnouncetoAll( &"CTF_TAKEN_BACK_AXIS", player.name );
    					else
    						player AnnouncetoAll( &"CTF_TAKEN_BACK_ALLIES", player.name );
    						
    					thread logEvent( "ctf_pickedup_dropped_flag", player );
    				}
    				
    				player pickupFlag( self );
    
    				friendlyAlias = "ctf_touchenemy";
    				enemyAlias = "ctf_enemy_touchenemy";
    				
    				thread [[level.onPlaySoundOnPlayers]]( friendlyAlias, self.team );
    				thread [[level.onPlaySoundOnPlayers]]( enemyAlias, [[level.getOtherTeam]]( self.team ) );
    							
    				thread [[level.onPlaySoundOnPlayers]]( game["flagTaken"][ player.pers["team"] ], player.pers["team"] );
    
    			}
    			else 
    			{
    				// CAPTURED THE FLAG !!
    				if( self.atbase )
    				{
    					if( isdefined( player.flag ) )
    					{
    						player.flag returnFlag( undefined );
    						player detachFlag( player.flag );
    						player.flag = undefined;
    						player.statusicon = "";
    
    						player.score += 10;
    						teamscore = getTeamScore( player.pers["team"] );
    						teamscore += 1;
    						setTeamScore( player.pers["team"], teamscore );
    						level notify( "update_allhud_score");
    	
    						if( player.pers["team"] == "allies" )
    							self AnnouncetoAll( &"CTF_CAPTURED_AXIS", player.name );
    						else
    							self AnnouncetoAll( &"CTF_CAPTURED_ALLIES", player.name );	
    
    						friendlyAlias = "ctf_touchcapture";
    						enemyAlias = "ctf_enemy_touchcapture";
    
    						thread [[level.onPlaySoundOnPlayers]]( game["flagCapped"][ [[level.getOtherTeam]]( player.pers["team"] ) ] );
    
    						thread [[level.onPlaySoundOnPlayers]]( friendlyAlias, player.pers["team"] );
    						thread [[level.onPlaySoundOnPlayers]]( enemyAlias, [[level.getOtherTeam]]( player.pers["team"] ) );
    						
    						thread logEvent( "ctf_captured_flag", player );
    
    						maps\mp\gametypes\_globallogic::checkScoreLimit();
    					}
    				}
    				else // RETURNED FLAG TO BASE !!
    				{							
    					self returnFlag( true );
    
    					if( self.team == "allies" )
    						self AnnouncetoAll( &"CTF_RETURNED_ALLIES", player.name );
    					else
    						self AnnouncetoAll( &"CTF_RETURNED_AXIS", player.name );
    						
    					thread [[level.onPlaySoundOnPlayers]]( "ctf_touchown", player.pers["team"] );
    						
    					thread logEvent( "ctf_returned_own_flag", player );
    					
    					player.score += 2;
    					level notify( "update_allhud_score" );
    				}
    			}
    		}
    		
    		wait( 0.05 );
    	}
    }
    Ockham's Razor: All things being equal, the SIMPLEST solution is the right one. And my method - the method used by modders before trigger_radius was introduced in COD2 - is to use a distance test of a script_origin against all players. Such a method is less server CPU heavy than SniperFire's method.
    Last edited by Tally; 5th December 2014 at 08:27.

  8. #7
    Assadministrator IzNoGoD's Avatar
    Join Date
    Aug 2012
    Posts
    1,718
    Thanks
    17
    Thanked 1,068 Times in 674 Posts
    1. You are using an implementation that emulates a trigger_radius, yet your screenshot shows a cube-like area, shouldnt it be a spherical area?
    2. Why not use distancesquared instead, this saves you a squareroot operation per frame per player, and squareroot operations are VERY expensive
    "Does not work" is an error report for a bug between keyboard and chair.

    All hail Artie Effem

  9. #8
    Brigadier General
    Join Date
    Oct 2012
    Posts
    994
    Thanks
    20
    Thanked 588 Times in 388 Posts
    Quote Originally Posted by IzNoGoD View Post
    1. You are using an implementation that emulates a trigger_radius, yet your screenshot shows a cube-like area, shouldnt it be a spherical area?
    2. Why not use distancesquared instead, this saves you a squareroot operation per frame per player, and squareroot operations are VERY expensive
    1. As you rightly say, I am EMULATING a trigger radius. Hence it can be square, rectangle, oblong, or bannana shaped, it doesn't matter. As long as the functionality is the same, it doesn't matter what shape it is.

    2. distanceSquared is not a built-in function in COD1, and I didn't emulate it or distance2d() (which I actually have in my utility files) because you actually need the height check in CTF as you move the trigger below the trigger radius in order to stop it triggering (cf. maps\mp\_utility::triggerOff()).

    For the record, and so I don't have to keep saying it, this is a list of things which AREN'T in COD1:

    no file functions. You cannot write to a file in any manner other than a log file. The only file formats you can read from are .GSC and .CFG;
    no including files (i.e. #include <directory><filename>), you have to either manually thread to them, or build function pointers;
    no trigger_radius;
    no isSubStr();
    no getSubStr();
    no strTok();
    no openscriptmenu command;
    no updated menu language at all, just pure Quake 3 functions and syntax;
    no closeingamemenu();
    no playerADS();
    only 2 channels for sound, so when you have 2 sounds playing simultaneously, if you play a 3rd, the sound of 1 of the others cuts out (the Quake 3 Team Arena engine natively has only 1 sound thread. It took other companies to implement sound functions such as 5.1 and EAX)
    no getTagOrigin();
    you cannot color light in COD1. It is just yellow, and the only way to color it is pass yellow light through a colored shader. In the COD2 engine, you can manipulate light directly, using 6 different parameters.
    no physicstrace();
    no fragbuttonpressed();
    no GetOffhandSecondaryClass() (because grenades go into their own weapon slots - the slots are "primary", "primaryb", "pistol", "grenade", "smokegrenade". You can put a grenade in the pistol slot and it will work, and vice versa, as long as you change the slot name);
    no "cg_fovscale" dvar;
    no "cg_fovmin" dvar (so you can't zoom in with a sniper scope like you can in COD2/COD4);
    no getPlayerAngles();

    That list is by no means exhaustive. It is just the things I have come across while building my current mod for COD1. the engine is seriously limited. I have reproduced the basic functions we all take for granted because I needed them, but there are things I want but can't have because they have to be built into the engine. Here are some of the basics I have built:

    Code:
    strTok( string, token )
    {
    	j = 0;
    	temparr[j] = "";	
    
    	for( i = 0; i < string.size; i++ )
    	{
    		if( string[i] == token )
    		{
    			j++;
    			temparr[j] = "";
    		}
    		else
    			temparr[j] += string[i];
    	}
    	
    	return( temparr );
    }
    
    getSubStr( string, start, end )
    {
    	temp = "";
    	count = 0;
    	if( start > 0 )
    	{
    		for( i=start; i < string.size; i++ )
    		{	
    			if( isDefined( end ) && count >= end )
    				break;
    
    			temp = temp + string[i];
    			count++;
    		}
    	}
    	else
    	{
    		for( i=0; i < string.size; i++ )
    		{
    			if( isDefined( end ) && i >= end )
    				break;
    				
    			temp = temp + string[i];
    		}
    	}
    	
    	return( temp );
    }
    
    isSubStr( str1, str2 )
    {
    	// compare string1 with string2
    	for( i=0; i < str2.size - str1.size; i++ )
    	{
    		temp = "";
    		for( j=0; j < str1.size; j++ )
    		{
    			temp = temp + str2[ i + j ];
    		}
    
    	   if( str1 == temp )
    		  return( true );
    	}
    
    	// if 1st comparision fails compare string2 with string1
    	for( i=0; i < str1.size - str2.size; i++ )
    	{
    		temp = "";
    		for( j=0; j < str2.size; j++ )
    		{
    			temp = temp + str1[ i + j ];
    		}
    
    	   if( str2 == temp )
    		  return( true );
    	}
    	
    	// all comparisons failed
    	return( false );
    }
    
    distance2d( a, b )
    {
    	return( distance( (a[0],a[1],0), (b[0],b[1],0) ) );
    }
    Last edited by Tally; 5th December 2014 at 10:17.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •