/************************************************************************
* Special item spawning/management code.  Mainly hacked from CTF, thanks
* Zoid.
* - zucc
*/
#include "g_local.h"



// time too wait between failures to respawn?
#define SPEC_RESPAWN_TIME       60
// time before they will get respawned
#define SPEC_TECH_TIMEOUT       60

char *tnames[] = {
        "item_quiet", "item_slippers", "item_vest", "item_band", "item_lasersight",
        NULL
};


void SpecThink(edict_t *spec);


static edict_t *FindSpecSpawn(void)
{
        edict_t *spot = NULL;
        int i = rand() % 16;

        while (i--)
                spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");
        if (!spot)
                spot = G_Find (spot, FOFS(classname), "info_player_deathmatch");

        if (spot == NULL)
        {
                gi.dprintf("Warning: failed to find special item spawn point!\n");
        }

        return spot;
}



static void SpawnSpec(gitem_t *item, edict_t *spot)
{
        edict_t *ent;
        vec3_t  forward, right;
        vec3_t  angles;

        ent = G_Spawn();

        ent->classname = item->classname;
        ent->item = item;
        ent->spawnflags = DROPPED_ITEM;
        ent->s.effects = item->world_model_flags;
        ent->s.renderfx = RF_GLOW;
        VectorSet (ent->mins, -15, -15, -15);
        VectorSet (ent->maxs, 15, 15, 15);
                // zucc dumb hack to make laser look like it is on the ground
        if (stricmp(item->pickup_name, LASER_NAME) == 0)                  
        {
                VectorSet (ent->mins, -15, -15, -1);
                VectorSet (ent->maxs, 15, 15, 1);
        }
        gi.setmodel (ent, ent->item->world_model);
        ent->solid = SOLID_TRIGGER;
        ent->movetype = MOVETYPE_TOSS;  
        ent->touch = Touch_Item;
        ent->owner = ent;

        angles[0] = 0;
        angles[1] = rand() % 360;
        angles[2] = 0;

        AngleVectors (angles, forward, right, NULL);
        VectorCopy (spot->s.origin, ent->s.origin);
        ent->s.origin[2] += 16;
        VectorScale (forward, 100, ent->velocity);
        ent->velocity[2] = 300;

        ent->nextthink = level.time + SPEC_RESPAWN_TIME;
        ent->think = SpecThink;

        gi.linkentity (ent);
}

void SpawnSpecs(edict_t *ent)
{
        gitem_t *spec;
        edict_t *spot;
        int i;
        i = 0;
        while (tnames[i]) {
                if ((spec = FindItemByClassname(tnames[i])) != NULL &&
                        (spot = FindSpecSpawn()) != NULL)
                        SpawnSpec(spec, spot);
                i++;
        }
}


void SpecThink(edict_t *spec)
{
        edict_t *spot;

        if ((spot = FindSpecSpawn()) != NULL) {
                SpawnSpec(spec->item, spot);
                G_FreeEdict(spec);
        } else {
                spec->nextthink = level.time + SPEC_RESPAWN_TIME;
                spec->think = SpecThink;
        }
}


static void MakeTouchSpecThink (edict_t *ent)
{
        ent->touch = Touch_Item;

                if ( deathmatch->value && !teamplay->value && !allitem->value )
        {
                        ent->nextthink = level.time + SPEC_RESPAWN_TIME - 1;
                        ent->think = SpecThink;
                }
                else if ( teamplay->value && !allitem->value )
                {
                        ent->nextthink = level.time + 60;
                        ent->think = G_FreeEdict;
                }
                                else // allitem->value is set
                                {
                                            ent->nextthink = level.time + 1;
                        ent->think = G_FreeEdict;
                                }
}




void Drop_Spec(edict_t *ent, gitem_t *item)
{
        edict_t *spec;

        spec = Drop_Item(ent, item);
        //gi.cprintf(ent, PRINT_HIGH, "Dropping special item.\n");
        spec->nextthink = level.time + 1;
        spec->think = MakeTouchSpecThink;
                //zucc this and the one below should probably be -- not = 0, if
                // a server turns on multiple item pickup.
        ent->client->pers.inventory[ITEM_INDEX(item)]--;
}

void DeadDropSpec(edict_t *ent)
{
        gitem_t *spec;
        edict_t *dropped;
        int i;

        i = 0;
        while (tnames[i]) {
                if ((spec = FindItemByClassname(tnames[i])) != NULL &&
                        ent->client->pers.inventory[ITEM_INDEX(spec)]) {
                        dropped = Drop_Item(ent, spec);
                        // hack the velocity to make it bounce random
                        dropped->velocity[0] = (rand() % 600) - 300;
                        dropped->velocity[1] = (rand() % 600) - 300;
                        dropped->nextthink = level.time + 1;
                        dropped->think = MakeTouchSpecThink;
                        dropped->owner = NULL;
                        ent->client->pers.inventory[ITEM_INDEX(spec)] = 0;
                }
                i++;
        }
}


// frees the passed edict!
void RespawnSpec(edict_t *ent)
{
        edict_t *spot;

        if ((spot = FindSpecSpawn()) != NULL)
                SpawnSpec(ent->item, spot);
        G_FreeEdict(ent);
}

void SetupSpecSpawn(void)
{
        edict_t *ent;

        if (level.specspawn)
                return;

        //gi.bprintf (PRINT_HIGH, "got into the setup\n");

        ent = G_Spawn();
        ent->nextthink = level.time + 4;
        ent->think = SpawnSpecs;
        level.specspawn = 1;
}
