////
// mc2.mapC
//
//  Example Code and initial library build
//
//////////////////////////////////////////////////////


//////////////////////////////////////////////////////
// new vars
vector entity::init_origin;             // For tracking flag movement
int entity::flag_state;                 // Allow us to keep track of all flags on the map
entity entity::carrier;                 // Allow us to keep track of all flags on the map

// Flag states
const int FLAG_HOME             = 1;
const int FLAG_AWAY             = 2;
const int FLAG_BEING_CARRIED    = 3;

int iscore;
void set_scoreboard(string boardname, int score);
void comm_scorer_think(entity self);

//////////////////////////////////////////////////////
// Team Wav playing and Message Printing Funcs
void playwavs_to_teams(entity ignore, int ftno, int nmytno, string wavforteam, string wavforenemy, string wavforelse)
{
    entity msgent;

    while ((msgent = find_ent(msgent, entvar, "player")) != NULL)
    {
        if (msgent != ignore)
        {
            if (msgent.team_no == ftno)
                play_clientsound(msgent, wavforteam, CHAN_AUTO, ATTN_NORM);
            else if (msgent.team_no == nmytno)
                play_clientsound(msgent, wavforenemy, CHAN_AUTO, ATTN_NORM);
            else
                play_clientsound(msgent, wavforelse, CHAN_AUTO, ATTN_NORM);
        }
    }
}

void print_team_updates(entity ignore, int ftno, int etno, string strforteam, string strforenemy, string strforelse)
{
    entlist fteam, eteam, ateam;

    // Create the friendly, enemy, and else lists
    fteam = get_players(entvar, ftno);
    eteam = get_players(entvar, etno);
    ateam = get_players(entvar, "player");   // Get all Players
    ateam = ateam - fteam;     // Remove players in fteam from list
    ateam = ateam - eteam;     // Remove players in eteam from list

    // Make sure ignore isn't in any lists
    fteam -= ignore;
    ateam -= ignore;
    eteam -= ignore;

    // Print the messages
    lprint(fteam, strforteam);
    lprint(eteam, strforenemy);
    lprint(ateam, strforelse);
}

//////////////////////////////////////////////////////
// Precaches
int entity::script_Precaches(int flags)
{
    precache_sound("weapons/bfg__l1a.wav");
    return TRUE;
}

//////////////////////////////////////////////////////
// Flaginfo Command Item

void flaginfo_command(entity ent)
{
    entity flag;

    // Cycle through all the flags, and dump the status of each
    while ((flag = find_ent(flag, entvar, "item_script")) != NULL)
    {
        if (flag.flag_state == FLAG_HOME)
        {
            cprint(ent, flag.name);
            cprint(ent, " is in its base.\n");
        }
        else if (flag.flag_state == FLAG_AWAY)
        {
            cprint(ent, flag.name);
            cprint(ent, " is lying around somewhere.\n");
        }
        else if (flag.flag_state == FLAG_BEING_CARRIED)
        {
            cprint(ent, flag.name);
            cprint(ent, " is being carried by ");
            cprint(ent, flag.carrier.name);
            cprint(ent, "\n");
        }
    }
}


int entity::spawn_flaginfo(int flags)
{
    return FALSE;
}


//////////////////////////////////////////////////////
// Flag Scripts
int entity::spawn_flag(int flags)
{
    //self.model = "models/items/tf_flag/tf_flag.md2";
    self.model = "models/items/healing/medium/tris.md2";
    self.flag_state = FLAG_HOME;
    return TRUE;
}


int entity::postspawn_flag(int flags)
{
    droptofloor(self);
    self.init_origin = self.origin;
    return TRUE;
}


int entity::touched_flag(entity other, int flags)
{
    entity msgent, flag;
    string fstr, estr, astr;

    if (other.team_no == self.owned_by_team)
    {
        if (self.init_origin != self.origin)
        {
            // Return Flag
            self.origin = self.init_origin;
            self.flag_state = FLAG_HOME;

            // Setup and Print Messages
            fstr = other.name + " Returned Your flag!\n";
            estr = "Your Flag was Captured!\n";
            astr = other.name + " Returned the " + other.name + "!\n";
            print_team_updates(other, other.team_no, other.team_no, fstr, NULL, astr);
            cprint(other, "You returned your flag\n");
            // Play Wav files
            playwavs_to_teams(self, other.team_no, other.team_no, "tf/maps/ctf/t_fl_return.wav", "", "tf/maps/ctf/t_en_fl_return.wav");
        }
        else
        {
            // If they've got any enemy flag, capture them
            while ((flag = find_ent(flag, entvar, "item_script")) != NULL)
            {
                
                if (flag.flag_state == FLAG_BEING_CARRIED AND flag.carrier == other)
                {
                    // Setup and Print Messages
                    fstr = "Your Team Captured the " + flag.name + "!\n";
                    estr = "Your Flag was Captured!\n";
                    astr = int_to_str(other.team_no) + " Team has Captured the " + flag.name + "!\n";
                    print_team_updates(other, other.team_no, flag.owned_by_team, fstr, estr, astr);
                    cprint(other, "You've Captured the ");
                    cprint(other, flag.name);
                    cprint(other, "!\n");
                    // Play Wav files
                    playwavs_to_teams(other, other.team_no, flag.owned_by_team, "tf/maps/ctf/t_en_fl_capt.wav", "tf/maps/ctf/t_fl_capt.wav", "tf/maps/ctf/t_en_fl_capt.wav");
                    play_clientsound(other, "tf/maps/ctf/p_en_fl_capt.wav", CHAN_AUTO, ATTN_NORM);

                    remove_item(other, flag.name, 0);
                    flag.origin = flag.init_origin;
                    flag.svflags = flag.svflags - (flag.svflags & SVF_NOCLIENT);
                    flag.solid = SOLID_TRIGGER;
                    flag.flag_state = FLAG_HOME;
                    flag.carrier = NULL;
    
                    iscore += 1;
                    set_scoreboard("my_board", iscore);
                }
            }
        }

        return FALSE;   // Refuse pickup
    }
	
    // Setup and Print Messages
    fstr = "Your Team has taken the " + self.name + "!\n";
    estr = "Your Flag has been taken by " + team_get_name(other.team_no) + "!\n";
    astr = team_get_name(other.team_no) + " Team has taken the " + self.name + "!\n";
    print_team_updates(other, other.team_no, self.owned_by_team, fstr, estr, astr);
    cprint(other, "You've taken the ");
    cprint(other, self.name);
    cprint(other, "!\n");
    // Play Wav files
    playwavs_to_teams(other, other.team_no, self.owned_by_team, "tf/maps/ctf/t_en_fl_taken.wav", "tf/maps/ctf/t_fl_taken.wav", "tf/maps/ctf/t_fl_taken.wav");
    play_clientsound(other, "tf/maps/ctf/p_en_fl_taken.wav", CHAN_AUTO, ATTN_NORM);

    return TRUE;
}


int entity::get_flag(entity other, int no_of_flags)
{
    self.flag_state = FLAG_BEING_CARRIED;
    self.carrier = other;

    // Since we're not going to let the Code remove this item,
    // we need to hide it ourselves
    self.svflags |= SVF_NOCLIENT;
    self.solid = SOLID_NOT;

    // Return False to prevent the Code from removing the item 
    // now its been picked up
    return FALSE;
}


int entity::drop_flag(entity other, int flags, int no_of_flags)
{
    entity flag;
    string fstr, estr, astr;

    if (flags & SF_DI_PLAYER_DROP OR flags & SF_DI_PLAYER_TRADE)
        return 0;               // Prevent Drop

    // Play Wav files
    playwavs_to_teams(self, other.team_no, self.owned_by_team, "tf/maps/ctf/t_en_fl_lost.wav", "tf/maps/ctf/t_fl_lost.wav", "tf/maps/ctf/t_fl_lost.wav");

    // We want to handle it ourselves
    remove_item(other, self.name, no_of_flags);

    // Cycle through all the flags, and find the correct flags
    while ((flag = find_ent(flag, entvar, "item_script")) != NULL)
    {
        if (flag.flag_state == FLAG_BEING_CARRIED AND flag.carrier == other)
        {
            throw_object(flag, other.origin);

            flag.solid = SOLID_TRIGGER;
            flag.flag_state = FLAG_AWAY;
            flag.carrier = NULL;

            // Setup and Print Messages
            fstr = other.name + " Lost the " + flag.name + "!\n";
            estr = int_to_str(other.team_no) + " Team Lost Your Flag!\n";
            astr = int_to_str(other.team_no) + " Team Lost the " + flag.name + "!\n";
            print_team_updates(other, other.team_no, flag.owned_by_team, fstr, estr, astr);
            cprint(other, "You Lost the ");
            cprint(other, flag.name);
            cprint(other, "!\n");
        }
    }
  
    return 0;
}



//////////////////////////////////////////////////////
// Custom Ent Definitions for Flags
entity_def 
{
    "classname"         "item_flag_team1"
    "spawnclass"        "item_script"
    "script_spawn"      "spawn_flag"
    "script_postspawn"  "postspawn_flag"
    "script_activate"   "touched_flag"
    "script_getitem"    "get_flag"
    "script_dropitem"   "drop_flag"
    "owned_by_team"     "1"
    "name"              "Blue Flag"
}

entity_def 
{
    "classname"         "item_flag_team2"
    "spawnclass"        "item_script"
    "script_spawn"      "spawn_flag"
    "script_postspawn"  "postspawn_flag"
    "script_activate"   "touched_flag"
    "script_getitem"    "get_flag"
    "script_dropitem"   "drop_flag"
    "owned_by_team"     "2"
    "name"              "Red Flag"
}


//////////////////////////////////////////////////////
// Custom Ent definition for Flaginfo Command Item
entity_def
{
    "classname"         "item_flaginfo"
    "spawnclass"        "item_script"
    "script_spawn"      "spawn_flaginfo"
    "command_func"      "flaginfo_command"
    "command_str"       "flaginfo"
    "name"              "flaginfo"
    "item_flags"        "96"                // IT_NOT_VISIBLE | IT_RESPAWN_KEEP
}

//////////////////////////////////////////////////////
// Custom Ent definition for Team Spawnpoints

entity_def
{
    "classname"         "info_player_team1"
    "spawnclass"        "info_player_deathmatch"
    // Criteria
    "team_no"           "1"     // Team 1 Only
}

entity_def
{
    "classname"         "info_player_team2"
    "spawnclass"        "info_player_deathmatch"
    // Criteria
    "team_no"           "2"     // Team 2 Only
}

entity_def
{
    "classname"         "info_player_team3"
    "spawnclass"        "info_player_deathmatch"
    // Criteria
    "team_no"           "4"     // Team 3 Only
}

entity_def
{
    "classname"         "info_player_team4"
    "spawnclass"        "info_player_deathmatch"
    // Criteria
    "team_no"           "8"     // Team 4 Only
}

//////////////////////////////////////////////////////
// GLOBAL SCRIPTS

// Called when the map starts
int entity::script_Worldspawn(int flags)
{
    entity ent;

    number_of_teams = 2;
    team_set_name(1, "Blue");
    team_set_name(2, "Red");

    // Command Point Scoring Entity
    ent = create_entity();
    ent.think = comm_scorer_think;
    ent.nextthink = time + 300;    // 30 Seconds

	return TRUE;
}


int entity::script_PlayerConnect(int flags)
{
    add_item(self, "flaginfo", 1);
	return TRUE; // yes, the player is allowed to join the game
}

//////////////////////////////////////////////////////
// flags is set to 1 if it's a grenade
int entity::touched_push(entity other, int flags)
{
	return TRUE;
}

// need to have touched blue spot to open door
int entity::touched_door(entity other, int flags)
{
	return TRUE;
}


int entity::script_TouchedBlueSpot(entity other, int flags)
{
	return TRUE;  // continue with activation
}

int entity::script_TouchedRedSpot(entity other, int flags)
{
	DEBUG1;
	return TRUE;
}

entity_def 
{
	"classname" 		"trigger_pushscum"
	"spawnclass" 		"trigger_push"
	"script_activate" 	"touched_push"
	"speed" 			"20"
}


//////////////////////////////////////////////////////
// Scoreboard
int entity::scoreboard_spawn(int flags)
{
    self.svflags |= SVF_NOCLIENT;
    return TRUE;
}

int entity::scoreboard_activate(entity other, int flags)
{
    return FALSE;       // Scoreboard is unusable
}

void set_scoreboard(string boardname, int score)
{
    entity ent;
    int    digit_score, unit, div;

    if (find_ent(ent, entvar, boardname) == NULL)
        error("invalid scoreboard name.\n");

    // Cycle through each of the scoreboard's digits,
    // setting each of their values by cycling through each of 
    // the digit's lines, making them visible/invisible.
    while ((ent = find_ent(ent, entvar, boardname)) != NULL)
    {
        div = score;
        unit = ent.count;
        while (unit > 1)
        {
            div = div / 10;
            unit -= 1;
        }
        digit_score = div % 10;

        if (ent.health == 1)
        {
            if (digit_score == 0 OR digit_score == 2 OR digit_score == 3 OR digit_score == 5 OR digit_score == 7 OR digit_score == 8 OR digit_score == 9)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 2)
        {
            if (digit_score == 0 OR digit_score == 1 OR digit_score == 2 OR digit_score == 3 OR digit_score == 4 OR digit_score == 7 OR digit_score == 8 OR digit_score == 9)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 3)
        {
            if (digit_score == 2 OR digit_score == 3 OR digit_score == 4 OR digit_score == 5 OR digit_score == 6 OR digit_score == 8 OR digit_score == 9)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 4)
        {
            if (digit_score == 0 OR digit_score == 1 OR digit_score == 3 OR digit_score == 4 OR digit_score == 5 OR digit_score == 6 OR digit_score == 7 OR digit_score == 8 OR digit_score == 9)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 5)
        {
            if (digit_score == 0 OR digit_score == 2 OR digit_score == 3 OR digit_score == 5 OR digit_score == 6 OR digit_score == 8)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 6)
        {
            if (digit_score == 0 OR digit_score == 2 OR digit_score == 6 OR digit_score == 8)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
        else if (ent.health == 7)
        {
            if (digit_score == 0 OR digit_score == 4 OR digit_score == 5 OR digit_score == 6 OR digit_score == 8 OR digit_score == 9)
                ent.svflags = ent.svflags - (ent.svflags & SVF_NOCLIENT);
            else
                ent.svflags |= SVF_NOCLIENT;
        }
    }
}

entity_def 
{
	"classname" 		"func_scoreboard_digit"
	"spawnclass" 		"func_script"
	"script_spawn" 	    "scoreboard_spawn"
    "script_activate"   "scoreboard_activate"
    // "name"  is the scoreboard's name
    // "count" is the digit's position in the scoreboard 
    //         (1 = units, 2 = 10s, 3 = 100s, etc)
    // "health" is the line's position in the digit
    //         use the damn prefab :)
}


////////////////////////////////////////////////////////////////////
// COMMAND POINT SYSTEM
////////////////////////////////////////////////////////////////////

// Command Point Scorer
void comm_scorer_think(entity self)
{
    string str1, str2;
    entity CP;
    int    team1cps, team2cps;

    // Cycle through all the CP's, counting the number each team controls
    while ((CP = find_ent(CP, entvar, "Command Point")) != NULL)
    {
        if (CP.count == 1)
            team1cps += 1;
        if (CP.count == 2)
            team2cps += 1;
    }

    str1 = int_to_str(team1cps) + " Command Point";
    if (team1cps != 1)
        str1 += "s";
    str1 += "!\n";
    str2 = int_to_str(team2cps) + " Command Point";
    if (team2cps != 1)
        str2 += "s";
    str2 += "!\n";

    tprint(1, NULL, "Your Team Controls ");
    tprint(1, NULL, str1);
    tprint(1, NULL, "The Enemy Team Controls ");
    tprint(1, NULL, str2);
    tprint(2, NULL, "Your Team Controls ");
    tprint(2, NULL, str2);
    tprint(2, NULL, "The Enemy Team Controls ");
    tprint(2, NULL, str1);

    self.nextthink = time + 300;
}

////////////////////////////////////////////////////////////////////
// Command Points Functions
int entity::comm_point_touched(entity other, int flags)
{
    string fstr, estr, astr, cstr;

    if ((get_num_items(other, "Blue Command Marker") > 0) OR (get_num_items(other, "Red Command Marker") > 0))
    {
        // Already owned by this team?
        if (self.count != 0 AND self.count == other.team_no)
            return FALSE;

        // Setup and Print Messages
        fstr = "Your Team has claimed a Command Point!\n";
        astr = "An Enemy team has claimed a Command Point!\n";
        estr = astr;
        cstr = "You've claimed a Command Point!\n";
        if (self.count != 0)
        {
            estr = "An Enemy team claimed one of Your Command Points!\n";
            cstr = "You've claimed an enemy Command Point!\n";
        }
        print_team_updates(other, other.team_no, self.count, fstr, estr, astr);
        cprint(other, cstr);

        // TODO: Play Wav files

        // Setup the Command Point
        self.count = other.team_no;

        // Remove the Command Marker from the Player
        // We can safely remove both types, since no-one can ever carry both
        remove_item(other, "Blue Command Marker", 0);
        remove_item(other, "Red Command Marker", 0);
    }
    
    return FALSE;
}

////////////////////////////////////////////////////////////////////
// Command Points Entity Definitions
entity_def 
{
    "classname"         "info_command_point"
    "spawnclass"        "trigger_script"
    "script_activate"   "comm_point_touched"
    "name"              "Command Point"
}

////////////////////////////////////////////////////////////////////
// Command Markers Functions

int entity::comm_marker_postspawn(int flags)
{
    droptofloor(self);
    return TRUE;
}


int entity::comm_marker_touched(entity other, int flags)
{
    // Only allow them to carry 1 at a time
    if (get_num_items(other, self.name) == 0)
        return TRUE;    

    return FALSE;
}


int entity::comm_marker_getitem(entity other, int no_of_flags)
{
    return FALSE;
}


int entity::comm_marker_dropitem(entity other, int flags, int no_of_flags)
{
    return 0;   // Lost when player dies
}

////////////////////////////////////////////////////////////////////
// Command Markers Entity Definitions

entity_def 
{
    "classname"         "item_comm_marker_team1"
    "spawnclass"        "item_script"
    "script_postspawn"  "comm_marker_postspawn"
    "script_activate"   "comm_marker_touched"
    "script_getitem"    "comm_marker_getitem"
    "script_dropitem"   "comm_marker_dropitem"
    "owned_by_team"     "1"
    "name"              "Blue Command Marker"
    "model"             "models/items/healing/medium/tris.md2"
    // Criteria
    "team_no"           "1"
}

entity_def 
{
    "classname"         "item_comm_marker_team2"
    "spawnclass"        "item_script"
    "script_postspawn"  "comm_marker_postspawn"
    "script_activate"   "comm_marker_touched"
    "script_getitem"    "comm_marker_getitem"
    "script_dropitem"   "comm_marker_dropitem"
    "owned_by_team"     "2"
    "name"              "Red Command Marker"
    "model"             "models/items/healing/medium/tris.md2"
    // Criteria
    "team_no"           "2"
}