/* server-side "both-game" functions.
 * Alliance Games
 */

#include "g_local.h"

int getGrapplePullSpeed(void) {
    return g_grapplePullSpeed.integer;
}

qboolean hasEnoughAmmo(const entityState_t *ent, const playerState_t *ps) {
    int itemQuantity = bg_itemlist[ent->modelindex].quantity;
    int itemCount = g_entities[ent->number].count;
    int quantity = (itemQuantity > itemCount) ? itemQuantity : itemCount;

    if (ps->ammo[bg_itemlist[ent->modelindex].giTag] < quantity)
        return qfalse;
    return qtrue;
}

qboolean BG_weaponsStayEnabled(void) {
    return weaponsStayEnabled();
}

qboolean BG_battleWeaponsEnabled(void) {
    return battleWeapons();
}

void QDECL BG_Printf(const char *msg, ...) {
    va_list argptr;
    char text[1024];

    va_start(argptr, msg);
    vsprintf(text, msg, argptr);
    va_end(argptr);

    trap_Printf(text);
}

int BG_gamemode(void) {
    return g_gamemode.integer;
}


// begin Joe triple rail
qboolean BG_tripleRailEnabled(void) {
    return g_tripleRail.integer;
}
// end Joe triple rail


// Myrkul: Movement options
int BG_rampJump(void) {
    return g_rampJump.integer;
}
int BG_strafeJump(void) {
    return g_strafeJump.integer;
}
int BG_airMove(void) {
    return g_airMove.integer;
}
int BG_airSpeed(void) {
    return g_airSpeed.integer;
}
int BG_grafting(void) {
    return g_grafting.integer;
}

// Myrkul: trains you to use strafe jump, always off on server
/*
int BG_strafeJumpTrainer(void) {
    return 0;
}
*/
/*
qboolean BG_IamClient(void) {
    if(!trap_Cvar_VariableValue( "sv_running" ))
        return qtrue;
    else
        return qfalse;
}

qboolean BG_IamServer(void) {
    if(trap_Cvar_VariableValue( "sv_running" ))
        return qtrue;
    else
        return qfalse;
}
*/

// dummy func, cgame has the real one, for bg_pmove.c
qboolean BG_noClientPredictFire(void) {
    return qfalse;
}

// Joe
void G_RunMissile2( gentity_t *ent, pmove_t *pm );

// Joe
#include "bg_battlebots.h"


void BG_check_Offhand_Grapple(pmove_t *pm) {
    trace_t tr;
    vec3_t origin, lastpos;
    gentity_t *hook;

    static trajectory_t pos[MAX_CLIENTS];

	if(g_grappleOnHand.integer)
		return;

    // not firing
    if(! (pm->cmd.buttons & BUTTON_GRAPPLE))
        return;

    // don't know about hook
    // happens maybe 1 time
    // hook entnum should be > MAX_CLIENTS - 1
    if(! pm->ps->stats[STAT_HOOK_ENTNUM]) {
        //        G_Printf("G: don't know about hook\n");
        return;
    }

    // don't need to
    if(pm->ps->pm_flags & PMF_GRAPPLE_PULL)
        return;

    hook = g_entities + pm->ps->stats[STAT_HOOK_ENTNUM];

    // don't trace backwards
    if(pm->ps->commandTime - 50 < hook->s.pos.trTime) {
        //         G_Printf("G: too early\n");
        return;
    }

    // get running trajectory
    // this will always happen first?
    if(hook->s.pos.trType == TR_LINEAR) {
        //        G_Printf("G: TR_LINEAR\n");

        // this is very repetitious
        pos[pm->ps->clientNum].trType = hook->s.pos.trType;
        pos[pm->ps->clientNum].trTime = hook->s.pos.trTime;
        VectorCopy(hook->s.pos.trBase,  pos[pm->ps->clientNum].trBase);
        VectorCopy(hook->s.pos.trDelta, pos[pm->ps->clientNum].trDelta);

        // old position
        BG_EvaluateTrajectory(&hook->s.pos, pm->ps->commandTime, origin);
        // current position
        BG_EvaluateTrajectory(&hook->s.pos, pm->ps->commandTime - 50,
                              lastpos);
    }

    // EV_MISSILE_MISS has happened from a normal trace
    // g_missile.c's trace often happens first, used saved trajectory
    else {
        //        G_Printf("TR_STATIONARY\n");

        BG_EvaluateTrajectory(&pos[pm->ps->clientNum], pm->ps->commandTime,
                              origin);
        BG_EvaluateTrajectory(&pos[pm->ps->clientNum], pm->ps->commandTime -
                              50, lastpos);

    }

    trap_Trace(&tr, lastpos, NULL, NULL, origin,
               pm->ps->clientNum, MASK_SHOT);
	
    if ( tr.fraction != 1) {
        // check if hooked a player
        gentity_t *other = &g_entities[tr.entityNum];
        if (other->s.eType == ET_PLAYER)
            return;

        // not sky hook and hit sky
        if (! BG_SkyHook() && (tr.surfaceFlags & SURF_NOIMPACT))
            return;

        //        G_Printf("G: pull turned on at pm->ps->commandTime %d\n",
        //                 pm->ps->commandTime);
		
        // place to pull to
        VectorCopy(tr.endpos, pm->ps->grapplePoint);
        // this is it
        pm->ps->pm_flags |= PMF_GRAPPLE_PULL;
    }
} // end BG_checkGrapple()

/*
qboolean BG_predictHook(void) {
    return g_predictHook.integer;
}
*/

qboolean BG_ammoRestore(void) {
    return g_ammoRestore.integer;
}

// Joe
qboolean BG_grappleEnabled(pmove_t *pm) {
    if (g_grappleGlobal.integer == 2)
        return qfalse;
    if (g_grappleGlobal.integer == 1)
        return qtrue;

    return pm->ps->stats[STAT_GRAPPLE];
}

qboolean BG_SkyHook(void) {
    return g_skyHook.integer;
}

int BG_getGrappleHookSpeed(void) {
    return g_grappleHookSpeed.integer;
}

qboolean BG_superShotgun(void) {
    if (g_superShotgun.integer)
        return qtrue;
    else
        return qfalse;
}
