// ************************************
// sgTeleporter written by nOs*Badger
// ************************************


class sgTeleporter extends sgBuilding;

var UTTeleEffect T;

var() string URL1;
var() string URL2;
//-----------------------------------------------------------------------------
// Product the user must have installed in order to enter the teleporter.
var() name ProductRequired;

//-----------------------------------------------------------------------------
// Teleporter destination flags.
var() bool    bChangesVelocity; // Set velocity to TargetVelocity.
var() bool    bChangesYaw;      // Sets yaw to teleporter's Rotation.Yaw
var() bool    bReversesX;       // Reverses X-component of velocity.
var() bool    bReversesY;       // Reverses Y-component of velocity.
var() bool    bReversesZ;       // Reverses Z-component of velocity.

// Teleporter flags
var() bool    bEnabled;         // Teleporter is turned on;

//-----------------------------------------------------------------------------
// Teleporter destination directions.
var() vector  TargetVelocity;   // If bChangesVelocity, set target's velocity to this.

// AI related
var Pawn TriggerPawn;     //used to tell AI how to trigger me
var Pawn TriggerPawn2;

var float LastFired;

//-----------------------------------------------------------------------------
// Teleporter destination functions.

replication
{
    reliable if( Role==ROLE_Authority )
        bEnabled, URL1, URL2;
    //reliable if ( bNetInitial && (Role == ROLE_Authority) )
    //    bChangesVelocity, bChangesYaw, bReversesX, bReversesY, bReversesZ, TargetVelocity; 
}

simulated event PostBeginPlay()
{
	Super.PostBeginPlay();
	URL1=GetTeleporterName();
	URL2=URL1;
}

simulated event Timer()
{
	Super.Timer();

	if ( SCount > 0 || Role != ROLE_Authority )
        	return;
}

simulated function Upgraded()
{
	Super.Upgraded();
}

simulated function string GetTeleporterName()
{
	return sPlayerIP@string(Team);
}

simulated event TakeDamage( int Damage, Pawn instigatedBy, Vector hitLocation, 
  Vector momentum, name damageType)
{
	local sgTeleporter teleDest;
	if (damageType != 'sgTeleporter')  
	{
		teleDest=FindOther();
    		if (teleDest!=None)
		teleDest.TakeDamage(Damage/2 , instigatedBy, teleDest.Location, momentum, 'sgTeleporter');	
	}
	Super.TakeDamage(Damage , instigatedBy, hitLocation, momentum, damageType);
}



simulated function FinishBuilding()
{
	Super.FinishBuilding();
	bEnabled=true;
}



// Accept an actor that has teleported in.
simulated function bool Accept( actor Incoming, Actor Source )
{
    local rotator newRot, oldRot;
    local int oldYaw;
    local float mag;
    local vector oldDir;
    local pawn P;

    // Move the actor here.
    Disable('Touch');
    //log("Move Actor here "$tag);
    newRot = Incoming.Rotation;
    if (bChangesYaw)
    {
        oldRot = Incoming.Rotation;
        newRot.Yaw = Rotation.Yaw;
        if ( Source != None )
            newRot.Yaw += (32768 + Incoming.Rotation.Yaw - Source.Rotation.Yaw);
    }

    if ( Pawn(Incoming) != None )
    {
        //tell enemies about teleport
        if ( Role == ROLE_Authority )
        {
            P = Level.PawnList;
            While ( P != None )
            {
                if (P.Enemy == Incoming)
                    P.LastSeenPos = Incoming.Location; 
                P = P.nextPawn;
            }
        }
        Pawn(Incoming).SetLocation(Location);
        if ( (Role == ROLE_Authority) 
            || (Level.TimeSeconds - LastFired > 0.5) )
        {
            Pawn(Incoming).SetRotation(newRot);
            Pawn(Incoming).ViewRotation = newRot;
            LastFired = Level.TimeSeconds;
        }
        Pawn(Incoming).MoveTimer = -1.0;
        Pawn(Incoming).MoveTarget = self;
        PlayTeleportEffect( Incoming, false);
    }
    else
    {
        if ( !Incoming.SetLocation(Location) )
        {
            Enable('Touch');
            return false;
        }
        if ( bChangesYaw )
            Incoming.SetRotation(newRot);
    }

    Enable('Touch');

    
    if (bChangesVelocity)
        Incoming.Velocity = TargetVelocity;
    else
    {
        if ( bChangesYaw )
        {
            if ( Incoming.Physics == PHYS_Walking )
                OldRot.Pitch = 0;
            oldDir = vector(OldRot);
            mag = Incoming.Velocity Dot oldDir;     
            Incoming.Velocity = Incoming.Velocity - mag * oldDir + mag * vector(Incoming.Rotation);
        } 
        if ( bReversesX )
            Incoming.Velocity.X *= -1.0;
        if ( bReversesY )
            Incoming.Velocity.Y *= -1.0;
        if ( bReversesZ )
            Incoming.Velocity.Z *= -1.0;
    }   

    // Play teleport-in effect.

    return true;
}
    
function PlayTeleportEffect(actor Incoming, bool bOut)
{
    if ( Incoming.IsA('Pawn') )
    {
        Incoming.MakeNoise(1.0);
        Level.Game.PlayTeleportEffect(Incoming, bOut, true);
    }
}

//-----------------------------------------------------------------------------
// Teleporter functions.

function Trigger( actor Other, pawn EventInstigator )
{
    local int i;

    //bEnabled = !bEnabled;
    if ( bEnabled ) //teleport any pawns already in my radius
        for (i=0;i<4;i++)
            if ( Touching[i] != None )
                Touch(Touching[i]);
}


simulated function Touch( actor Other )
{

	local sgTeleporter teleDest;
	local Pawn p;

	if ( !bEnabled) return;
	if( !Other.bCanTeleport ) return;
	if ( bDisabledByEMP) return;

	teleDest=FindOther(Pawn(Other));

	if( teleDest != None && Team == Pawn(Other).PlayerReplicationInfo.Team && teleDest.bEnabled)
	{
		//announceall(Team@" "@Pawn(Other).PlayerReplicationInfo.Team);

                // Teleport the actor into the other teleporter.
		if ( Other.IsA('Pawn') )
			PlayTeleportEffect( Pawn(Other), false);

		teleDest.Accept( Other, self );
		if((Event != '') && Other.IsA('Pawn') )
		for ( p = Level.PawnList; p != None; p = p.nextPawn ) {
			if (p.playerreplicationinfo.Team == Team)
				p.Trigger( Other, Other.Instigator ); }
	}

}

simulated function sgTeleporter FindOther(optional Pawn instigator)
{
	local Pawn p;
	local sgTeleporter teleDest;
	local sgTeleNetwork sgTN;
	local bool bTeleNetwork;
	local bool bNext;
	local int iTel;
	local bool bFirst;
	local sgTeleporter firstteleDest;

	if (instigator!=None)
		bTeleNetwork = (sgTeleNetwork(instigator.FindInventoryType(class'sgTeleNetwork')) != None);

    	for ( p = Level.PawnList; p != None; p = p.nextPawn )
		if (p.IsA('sgTeleporter'))
		{

			teleDest=sgTeleporter(p);
			if ( instigator != None && instigator.PlayerReplicationInfo != None &&
			     teleDest.Team == instigator.PlayerReplicationInfo.Team)
			{
				if (bTeleNetwork)
				{
					if (!bFirst) { firstteleDest = teleDest; bFirst = true; }
					if (teleDest == Self) bNext = true;
					else if (bNext == true) return teleDest;
				}
				else
				if (teleDest.URL2==URL1 && teleDest != Self) return teleDest;
			}
		}
    	return firstteleDest;
}

simulated function Actor SpecialHandling(Pawn Other)
{
    local int i;
    local vector Dist2D;
    if ( bEnabled && (Other.RouteCache[1] != None)
        && Other.RouteCache[1].IsA('sgTeleporter'))// && (string(Other.RouteCache[1].tag)~=URL) )
    {
        if ( Abs(Location.Z - Other.Location.Z) < CollisionHeight + Other.CollisionHeight )
        {
            Dist2D = Location - Other.Location;
            Dist2D.Z = 0;
            if ( VSize(Dist2D) < CollisionRadius + Other.CollisionRadius )
                Touch(Other);
        }   
        return self;
    }

    if (TriggerPawn == None)
    {
        FindTriggerPawn();
        if (TriggerPawn == None)
            return None;
    }

    if ( (TriggerPawn2 != None) 
        && (VSize(TriggerPawn2.Location - Other.Location) < VSize(TriggerPawn.Location - Other.Location)) )
        return TriggerPawn2;
                    
    return TriggerPawn;            
}  

simulated function FindTriggerPawn()
{
    local Pawn p;

    TriggerPawn = None;
    TriggerPawn2 = None;

    p = FindOther();
    if (p!=None)
    {
            //if ( Counter(A) != None )
            //    return;
            if (TriggerPawn == None)
                TriggerPawn = p;
            else
            {
                TriggerPawn2 = p;
                return;
            }
    }
}

defaultproperties
{
    bChangesVelocity=True
    BuildingName="Teleporter"
    BuildCost=500
    UpgradeCost=0
    BuildTime=15.00
    MaxEnergy=2000.00
    Model=LodMesh'Botpack.Tele2'
    SkinRedTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.PlatformSkinT0'
    SkinBlueTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.PlatformSkinT1'
    SkinGreenTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.PlatformSkinT2'
    SkinYellowTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.PlatformSkinT3'
    SpriteRedTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.MotionAlarmSpriteT0'
    SpriteBlueTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.MotionAlarmSpriteT1'
    SpriteGreenTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.MotionAlarmSpriteT2'
    SpriteYellowTeam=Texture'SiegeUltimateRC7UB01Media.U.BuildingMaps.MotionAlarmSpriteT3'
    NumOfMFX=2
    MFXrotX=(Pitch=20000,Yaw=20000,Roll=20000),
    Mesh=LodMesh'Botpack.Tele2'
    MultiSkins(0)=Texture'SiegeUltimateRC7UB01Media.GFX.sgContSpriteT0'
    MultiSkins(1)=Texture'SiegeUltimateRC7UB01Media.GFX.sgContSpriteT1'
    MultiSkins(2)=Texture'SiegeUltimateRC7UB01Media.GFX.sgContSpriteT2'
    MultiSkins(3)=Texture'SiegeUltimateRC7UB01Media.GFX.sgContSpriteT3'
    SoundVolume=128
    CollisionRadius=18.00
    CollisionHeight=32.00
    
    bNoUpgrade=True
}
