Пример #1
0
void PlagueCloudSpawn (edict_t *ent)
{
	float	radius;
	edict_t *e=NULL;

	if (ent->myskills.abilities[PLAGUE].disable)
		return;

	if (!V_CanUseAbilities(ent, PLAGUE, 0, false))
		return;

	if ((ent->myskills.class_num == CLASS_POLTERGEIST) && !ent->mtype && !PM_PlayerHasMonster(ent))
		return; // can't use this in human form

	radius = PLAGUE_DEFAULT_RADIUS+PLAGUE_ADDON_RADIUS*ent->myskills.abilities[PLAGUE].current_level;

	if (radius > PLAGUE_MAX_RADIUS)
		radius = PLAGUE_MAX_RADIUS;

	// find someone nearby to infect
	while ((e = findradius(e, ent->s.origin, radius)) != NULL)
	{
		if (!G_ValidTarget(ent, e, true))
			continue;
	//	if (HasActiveCurse(e, CURSE_PLAGUE))
		if (que_typeexists(e->curses, CURSE_PLAGUE))
			continue;
		// holy water grants temporary immunity to curses
		if (e->holywaterProtection > level.time)
			continue;

		PlagueCloud(ent, e);
	}
}
Пример #2
0
void MindAbsorb(edict_t *ent) 
{  
	edict_t *target = NULL;  
	int radius;  
	int take;  
	int total;
	int abilityLevel = ent->myskills.abilities[MIND_ABSORB].current_level;   
	
	if(ent->myskills.abilities[MIND_ABSORB].disable)   
		return;   
	if (!V_CanUseAbilities(ent, MIND_ABSORB, 0, false))   
		return;   //Cloaking and chat protected players can't steal anything
	if ((ent->flags & FL_CHATPROTECT) || (ent->svflags & SVF_NOCLIENT))   
		return;   
	
	take = MIND_ABSORB_AMOUNT_BASE + (MIND_ABSORB_AMOUNT_BONUS * abilityLevel);  
	radius = MIND_ABSORB_RADIUS_BASE + (MIND_ABSORB_RADIUS_BONUS * abilityLevel);   
	
	// scan for targets  
	while ((target = findclosestradius(target, ent->s.origin, radius)) != NULL)  
	{   
		if (target == ent)    
			continue;   
		if (!G_ValidTarget(ent, target, true))    
			continue;   
		
		total = 0;
		
		if (target->client)
		{
			if (target->client->pers.inventory[power_cube_index] < take)
				total += target->client->pers.inventory[power_cube_index];
			else
				total += take;

			target->client->pers.inventory[power_cube_index] -= total;

			// a bit of amnesia too
			target->client->ability_delay = level.time + 0.1 * abilityLevel;  
		}
		else
		{
			if (target->health < take)
				total += target->health;
			else
				total += take;
		}

		//Cap cube count to max cubes 
		if (ent->client->pers.inventory[power_cube_index] + total < MAX_POWERCUBES(ent))
			ent->client->pers.inventory[power_cube_index] += total;
		else if (ent->client->pers.inventory[power_cube_index] < MAX_POWERCUBES(ent))
			ent->client->pers.inventory[power_cube_index] = MAX_POWERCUBES(ent); 

		// those powercubes hurt!  
		T_Damage(target, ent, ent, vec3_origin, vec3_origin, vec3_origin, total, 0, DAMAGE_NO_ARMOR, MOD_MINDABSORB);
	}  
}
Пример #3
0
void Cmd_WormHole_f (edict_t *ent)
{
	// allow wormhole exit
	if (ent->flags & FL_WORMHOLE)
		SpawnWormhole(ent, 0);

	if (!V_CanUseAbilities(ent, BLACKHOLE, BLACKHOLE_COST, true))
		return;
	if (ent->myskills.abilities[BLACKHOLE].disable)
		return;

	SpawnWormhole(ent, 1);
}
Пример #4
0
void Cmd_Decoy_f (edict_t *ent)
{
	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_Decoy_f()\n", ent->client->pers.netname);

	if (!V_CanUseAbilities(ent, DECOY, M_DEFAULT_COST, true))
		return;

	if (MirroredEntitiesExist(ent))
	{
		gi.cprintf(ent, PRINT_HIGH, "You already have decoys out!\n");
		return;
	}

	SpawnDrone(ent, 20, false);
}
Пример #5
0
void Cmd_Curse(edict_t *ent)
{
	int range, radius, talentLevel, cost=CURSE_COST;
	float duration;
	edict_t *target = NULL;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_Curse()\n", ent->client->pers.netname);

	//Talent: Cheaper Curses
	if ((talentLevel = getTalentLevel(ent, TALENT_CHEAPER_CURSES)) > 0)
		cost *= 1.0 - 0.1 * talentLevel;

	if (!V_CanUseAbilities(ent, CURSE, cost, true))
		return;

	range = CURSE_DEFAULT_INITIAL_RANGE + CURSE_DEFAULT_ADDON_RANGE * ent->myskills.abilities[CURSE].current_level;
	radius = CURSE_DEFAULT_INITIAL_RADIUS + CURSE_DEFAULT_ADDON_RADIUS * ent->myskills.abilities[CURSE].current_level;
	duration = CURSE_DURATION_BASE + (CURSE_DURATION_BONUS * ent->myskills.abilities[CURSE].current_level);

	//Talent: Evil curse
	talentLevel = getTalentLevel(ent, TALENT_EVIL_CURSE);
	if(talentLevel > 0)
		duration *= 1.0 + 0.25 * talentLevel;

	if (duration < 1)
		duration = 1;

	CurseRadiusAttack(ent, CURSE, range, radius, duration, true);

	//Finish casting the spell
	//ent->client->ability_delay = level.time + CURSE_DELAY;
	ent->myskills.abilities[CURSE].delay = level.time + CURSE_DELAY;
	ent->client->pers.inventory[power_cube_index] -= cost;

	target = curse_Attack(ent, CURSE, radius, duration, true);

	//Play the spell sound!
	gi.sound(ent, CHAN_ITEM, gi.soundindex("curses/curse.wav"), 1, ATTN_NORM, 0);
	
}
Пример #6
0
void Cmd_LowerResist (edict_t *ent)
{
	int range, radius, talentLevel, cost=LOWER_RESIST_COST;
	float duration;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_LowerResist()\n", ent->client->pers.netname);

	//Talent: Cheaper Curses
	if ((talentLevel = getTalentLevel(ent, TALENT_CHEAPER_CURSES)) > 0)
		cost *= 1.0 - 0.1 * talentLevel;

	if (!V_CanUseAbilities(ent, LOWER_RESIST, cost, true))
		return;

	range = LOWER_RESIST_INITIAL_RANGE + LOWER_RESIST_ADDON_RANGE * ent->myskills.abilities[LOWER_RESIST].current_level;
	radius = LOWER_RESIST_INITIAL_RADIUS + LOWER_RESIST_ADDON_RADIUS * ent->myskills.abilities[LOWER_RESIST].current_level;
	duration = LOWER_RESIST_INITIAL_DURATION + LOWER_RESIST_ADDON_DURATION * ent->myskills.abilities[LOWER_RESIST].current_level;

	// evil curse talent
	talentLevel = getTalentLevel(ent, TALENT_EVIL_CURSE);
	if(talentLevel > 0)
		duration *= 1.0 + 0.25 * talentLevel;

	if (duration < 1)
		duration = 1;

	CurseRadiusAttack(ent, LOWER_RESIST, range, radius, duration, true);

	//Finish casting the spell
	//ent->client->ability_delay = level.time + LOWER_RESIST_DELAY;
	ent->myskills.abilities[LOWER_RESIST].delay = level.time + LOWER_RESIST_DELAY;
	ent->client->pers.inventory[power_cube_index] -= cost;

	//Play the spell sound!
	gi.sound(ent, CHAN_ITEM, gi.soundindex("curses/lowerresist.wav"), 1, ATTN_NORM, 0);

}
Пример #7
0
void Cmd_PlayerToMedic_f (edict_t *ent)
{
	vec3_t	boxmin, boxmax;
	trace_t	tr;
	int cost = MEDIC_INIT_COST;
	//Talent: More Ammo
	int talentLevel = getTalentLevel(ent, TALENT_MORE_AMMO);

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_PlayerToMedic_f()\n", ent->client->pers.netname);

	// try to switch back
	if (ent->mtype || PM_PlayerHasMonster(ent))
	{
		// don't let a player-tank unmorph if they are cocooned
		if (ent->owner && ent->owner->inuse && ent->owner->movetype == MOVETYPE_NONE)
			return;

		if (que_typeexists(ent->curses, 0))
		{
			safe_cprintf(ent, PRINT_HIGH, "You can't morph while cursed!\n");
			return;
		}

		V_RestoreMorphed(ent, 0);
		return;
	}

	//Talent: Morphing
	if(getTalentSlot(ent, TALENT_MORPHING) != -1)
		cost *= 1.0 - 0.25 * getTalentLevel(ent, TALENT_MORPHING);

//	if (!G_CanUseAbilities(ent, ent->myskills.abilities[MEDIC].current_level, cost))
//		return;

	if (!V_CanUseAbilities(ent, MEDIC, cost, true))
		return;

	if (HasFlag(ent))
	{
		safe_cprintf(ent, PRINT_HIGH, "Can't morph while carrying flag!\n");
		return;
	}

	// make sure don't get stuck in a wall
	VectorSet (boxmin, -24, -24, -24);
	VectorSet (boxmax, 24, 24, 32);
	tr = gi.trace(ent->s.origin, boxmin, boxmax, ent->s.origin, ent, MASK_SHOT);
	if (tr.fraction<1)
	{
		safe_cprintf(ent, PRINT_HIGH, "Not enough room to morph!\n");
		return;
	}
	
	V_ModifyMorphedHealth(ent, MORPH_MEDIC, true);

	VectorCopy(boxmin, ent->mins);
	VectorCopy(boxmax, ent->maxs);

	ent->monsterinfo.attack_finished = level.time + 0.5;// can't attack immediately

	ent->client->pers.inventory[power_cube_index] -= cost;
	ent->client->ability_delay = level.time + MEDIC_DELAY;

	ent->mtype = MORPH_MEDIC;
	ent->s.modelindex = gi.modelindex ("models/monsters/medic/tris.md2");
	ent->s.modelindex2 = 0;

	if (!ent->myskills.administrator)
		ent->s.skinnum = 0;
	else
		ent->s.skinnum = 2; // commander

	// set maximum hyperblaster ammo
	ent->myskills.abilities[MEDIC].max_ammo = MEDIC_HB_INITIAL_AMMO+MEDIC_HB_ADDON_AMMO
		*ent->myskills.abilities[MEDIC].current_level;

	// Talent: More Ammo
	// increases ammo 10% per talent level
	if(talentLevel > 0) ent->myskills.abilities[MEDIC].max_ammo *= 1.0 + 0.1*talentLevel;

	// give them some starting ammo
	ent->myskills.abilities[MEDIC].ammo = MEDIC_HB_START_AMMO;

	ent->client->refire_frames = 0; // reset charged weapon
	ent->client->weapon_mode = 0; // reset weapon mode
	lasersight_off(ent);

	gi.sound (ent, CHAN_WEAPON, gi.soundindex("spells/morph.wav") , 1, ATTN_NORM, 0);
}
Пример #8
0
void Cmd_PlayerToParasite_f (edict_t *ent)
{
	int para_cubecost = PARASITE_INIT_COST;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_PlayerToParasite_f()\n", ent->client->pers.netname);

	// try to switch back
	if (ent->mtype || PM_PlayerHasMonster(ent))
	{
		// don't let a player-tank unmorph if they are cocooned
		if (ent->owner && ent->owner->inuse && ent->owner->movetype == MOVETYPE_NONE)
			return;

		if (que_typeexists(ent->curses, 0))
		{
			gi.cprintf(ent, PRINT_HIGH, "You can't morph while cursed!\n");
			return;
		}

		V_RestoreMorphed(ent, 0);
		return;
	}

	//Talent: Morphing
	if(getTalentSlot(ent, TALENT_MORPHING) != -1)
		para_cubecost *= 1.0 - 0.25 * getTalentLevel(ent, TALENT_MORPHING);

//	if (!G_CanUseAbilities(ent, ent->myskills.abilities[BLOOD_SUCKER].current_level, para_cubecost))
	//	return;
	if (!V_CanUseAbilities(ent, BLOOD_SUCKER, para_cubecost, true))
		return;

	if (HasFlag(ent))
	{
		gi.cprintf(ent, PRINT_HIGH, "Can't morph while carrying flag!\n");
		return;
	}

	V_ModifyMorphedHealth(ent, M_MYPARASITE, true);

	ent->wait = level.time + 0.5;// can't attack immediately

	ent->client->pers.inventory[power_cube_index] -= para_cubecost;
	ent->client->ability_delay = level.time + PARASITE_DELAY;

	ent->mtype = M_MYPARASITE;
	ent->s.modelindex = gi.modelindex ("models/monsters/parasite/tris.md2");
	ent->s.modelindex2 = 0;
	ent->s.skinnum = 0;

	// decloak
	ent->svflags &= ~SVF_NOCLIENT;
	ent->client->cloaking = false;
	ent->client->cloakable = 0;

	ent->maxs[2] = 8;
	ent->viewheight = 0;

	ent->client->refire_frames = 0; // reset charged weapon
	ent->client->weapon_mode = 0; // reset weapon mode
	lasersight_off(ent);

	gi.sound (ent, CHAN_WEAPON, gi.soundindex("spells/morph.wav") , 1, ATTN_NORM, 0);
}
Пример #9
0
void SpawnTotem(edict_t *ent, int abilityID)
{
	int			talentLevel, cost=TOTEM_COST;
	edict_t		*totem;
	int			totemType;
	vec3_t		start;//GHz 4.32

	// cost is doubled if you are a flyer or cacodemon below skill level 5
	if ((ent->mtype == MORPH_FLYER && ent->myskills.abilities[FLYER].current_level < 5) 
		|| (ent->mtype == MORPH_CACODEMON && ent->myskills.abilities[CACODEMON].current_level < 5))
		cost *= 2;

	if(!V_CanUseAbilities(ent, abilityID, cost, true))
		return;
	
	if (ctf->value && abilityID == FIRE_TOTEM 
		&& (CTF_DistanceFromBase(ent, NULL, CTF_GetEnemyTeam(ent->teamnum)) < CTF_BASE_DEFEND_RANGE))
	{
		safe_cprintf(ent, PRINT_HIGH, "Can't build in enemy base!\n");
		return;
	}

	//Determine the totem type.
	switch(abilityID)
	{
	case FIRE_TOTEM:		totemType = TOTEM_FIRE;		break;
	case WATER_TOTEM:		totemType = TOTEM_WATER;	break;
	case AIR_TOTEM:			totemType = TOTEM_AIR;		break;
	case EARTH_TOTEM:		totemType = TOTEM_EARTH;	break;
	case DARK_TOTEM:		totemType = TOTEM_DARKNESS;	break;
	case NATURE_TOTEM:		totemType = TOTEM_NATURE;	break;
	default: return;
	}

	//Can't create too many totems.
	if(ent->totem1)
	{
		//Can't have more than one totem without the talent.
		/*if(getTalentLevel(ent, TALENT_TOTEM) < 1)
		{
			safe_cprintf(ent, PRINT_HIGH, "You already have a totem active.\n");
			return;
		}
		//Can't have more than two totems.
		else*/ if(ent->totem2)
		{
			safe_cprintf(ent, PRINT_HIGH, "You already have two totems active.\n");
			return;
		}
		//Can't have two totems of opposite alignment.
		else
		{
			int opposite = 0;
			switch(ent->totem1->mtype)
			{
			case TOTEM_FIRE:		opposite = TOTEM_WATER;		break;
			case TOTEM_WATER:		opposite = TOTEM_FIRE;		break;
			case TOTEM_AIR:			opposite = TOTEM_EARTH;		break;
			case TOTEM_EARTH:		opposite = TOTEM_AIR;		break;
			case TOTEM_DARKNESS:	opposite = TOTEM_NATURE;	break;
			case TOTEM_NATURE:		opposite = TOTEM_DARKNESS;	break;
			}
			if(totemType == opposite)
			{
				safe_cprintf(ent, PRINT_HIGH, "You can't create two totems of opposite elemental alignment.\n");
				return;
			}
			else if(totemType == ent->totem1->mtype)
			{
				safe_cprintf(ent, PRINT_HIGH, "You can't create totems of the same type.\n");
				return;
			}
		}
	}

	//Drop a totem.
	totem = DropTotem(ent);
	totem->mtype = totemType;
	totem->monsterinfo.level = ent->myskills.abilities[abilityID].current_level;
	totem->classname = "totem";
	/*totem->owner =*/ totem->activator = ent;
	totem->think = totem_general_think;
	totem->touch = totem_touch;
	totem->nextthink = level.time + FRAMETIME*2;
	totem->delay = level.time + 0.5;
	totem->die = totem_die;

	//TODO: update this with the new model.
	totem->s.modelindex = gi.modelindex("models/items/mega_h/tris.md2");
	//totem->s.angles[ROLL] = 270;
	VectorSet (totem->mins, -8, -8, -12);
	VectorSet (totem->maxs, 8, 8, 16);
	VectorCopy(ent->s.origin, totem->s.origin);
	
	totem->health = TOTEM_HEALTH_BASE + TOTEM_HEALTH_MULT * totem->monsterinfo.level;

	//Talent: Totemic Focus - increases totem health
	if((talentLevel = getTalentLevel(ent, TALENT_TOTEM)) > 0)
		totem->health *= 1 + 0.1666 * talentLevel;

	if (totemType == TOTEM_FIRE)
	{
		// fire totem is much tougher
		totem->health *= 2;
		// fire totem has a longer delay
		totem->delay = level.time + 2.0;
	}

	totem->max_health = totem->health*2;

	//Not sure if this stuff is needed (Archer)
	totem->svflags |= SVF_MONSTER;
	totem->takedamage = DAMAGE_AIM;
	totem->clipmask = MASK_MONSTERSOLID;

	//Back to stuff we need
	totem->mass = 200;
	totem->movetype = MOVETYPE_TOSS;//MOVETYPE_WALK;
	totem->deadflag = DEAD_NO;
	totem->svflags &= ~SVF_DEADMONSTER;	
	totem->solid = SOLID_BBOX;

	//Graphical effects
	//TODO: update this to make it look better.
	totem->s.effects |= EF_PLASMA | EF_COLOR_SHELL | EF_SPHERETRANS;
	switch(totemType)
	{
	case TOTEM_FIRE:
		totem->s.effects |= 262144;		//red radius light
		totem->s.renderfx |= RF_SHELL_RED;
		break;
	case TOTEM_WATER:
		totem->s.effects |= 524288;		//blue radius light
		totem->s.renderfx |= RF_SHELL_CYAN;
		break;
	case TOTEM_AIR:
		totem->s.effects |= 64;			//bright light radius
		totem->s.renderfx |= RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_GREEN;		
		break;
	case TOTEM_EARTH:
		totem->s.renderfx |= RF_SHELL_YELLOW;
		break;
	case TOTEM_DARKNESS:
		totem->s.effects |= 2147483648;		//strange darkness effect
		//totem->s.renderfx |= RF_SHELL_RED | RF_SHELL_BLUE;
		break;
	case TOTEM_NATURE:
		totem->s.effects |= 128;	//green radius light
		totem->s.renderfx |= RF_SHELL_GREEN;
		break;
	}
//GHz 4.32
	if (!G_GetSpawnLocation(ent, 64, totem->mins, totem->maxs, start))
	{
		G_FreeEdict(totem);
		return;
	}

	VectorCopy(start, totem->s.origin);
	gi.linkentity(totem);
//GHz
	if(!ent->totem1)	ent->totem1 = totem;
	else				ent->totem2 = totem;

	ent->client->pers.inventory[ITEM_INDEX(Fdi_POWERCUBE)] -= cost;

	// calling entity made a sound, used to alert monsters
	ent->lastsound = level.framenum;
	ent->client->ability_delay = level.time + 1.3;
}
Пример #10
0
void Cmd_PlayerToBerserk_f (edict_t *ent)
{
	int cost = BERSERK_COST;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_PlayerToBerserk_f()\n", ent->client->pers.netname);

	// try to switch back
	if (ent->mtype || PM_PlayerHasMonster(ent))
	{
		// don't let a player-tank unmorph if they are cocooned
		if (ent->owner && ent->owner->inuse && ent->owner->movetype == MOVETYPE_NONE)
			return;

		if (que_typeexists(ent->curses, 0))
		{
			safe_cprintf(ent, PRINT_HIGH, "You can't morph while cursed!\n");
			return;
		}

		V_RestoreMorphed(ent, 0);
		return;
	}

	//Talent: Morphing
    if (vrx_get_talent_slot(ent, TALENT_MORPHING) != -1)
        cost *= 1.0 - 0.25 * vrx_get_talent_level(ent, TALENT_MORPHING);

	if (!V_CanUseAbilities(ent, BERSERK, cost, true))
		return;

	if (HasFlag(ent) && !hw->value)
	{
		safe_cprintf(ent, PRINT_HIGH, "Can't morph while carrying flag!\n");
		return;
	}

	V_ModifyMorphedHealth(ent, MORPH_BERSERK, true);

	ent->monsterinfo.attack_finished = level.time + 0.5;// can't attack immediately

	ent->client->pers.inventory[power_cube_index] -= cost;
	ent->client->ability_delay = level.time + BERSERK_DELAY;

	ent->mtype = MORPH_BERSERK;
	ent->s.modelindex = gi.modelindex ("models/monsters/berserk/tris.md2");
	ent->s.modelindex2 = 0;
	ent->s.skinnum = 0;

	// undo crouching / ducked state
	// try asking their client to get up
	stuffcmd(ent, "-movedown\n");
	// if their client ignores the command, force them up
	if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
	{
		ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
		ent->viewheight = 22;
		ent->maxs[2] += 28;
	}
	
	ent->client->refire_frames = 0; // reset charged weapon
	ent->client->weapon_mode = 0; // reset weapon mode
	ent->client->pers.weapon = NULL;
	ent->client->ps.gunindex = 0;
	lasersight_off(ent);

    gi.sound(ent, CHAN_WEAPON, gi.soundindex("abilities/morph.wav"), 1, ATTN_NORM, 0);
}
Пример #11
0
void Cmd_Bless(edict_t *ent)
{
	int radius;
	float duration, cooldown;
	edict_t *target = NULL;

	if (debuginfo->value)
		gi.dprintf("DEBUG: %s just called Cmd_Bless()\n", ent->client->pers.netname);

	if(ent->myskills.abilities[BLESS].disable)
		return;

	//if (!G_CanUseAbilities(ent, ent->myskills.abilities[BLESS].current_level, BLESS_COST))
	//	return;

	if (!V_CanUseAbilities(ent, BLESS, BLESS_COST, true))
		return;

	radius = SHAMAN_CURSE_RADIUS_BASE + (SHAMAN_CURSE_RADIUS_BONUS * ent->myskills.abilities[BLESS].current_level);
	duration = BLESS_DURATION_BASE + (BLESS_DURATION_BONUS * ent->myskills.abilities[BLESS].current_level);

	//Blessing self?
	if (Q_strcasecmp(gi.argv(1), "self") == 0)
	{
		if (HasFlag(ent))
		{
			gi.cprintf(ent, PRINT_HIGH, "Can't use this while carrying the flag!\n");
			return;
		}

		if (!curse_add(ent, ent, BLESS, 0, duration))
		{
			gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n");
			return;
		}
		target = ent;
	}
	else
	{
		target = curse_Attack(ent, BLESS, radius, duration, false);
	}

	if (target != NULL)
	{
		que_t *slot = NULL;

		//Finish casting the spell
		ent->client->ability_delay = level.time + BLESS_DELAY;
		ent->client->pers.inventory[power_cube_index] -= BLESS_COST;

		cooldown = 2.0 * duration;
		if (cooldown > 10.0)
			cooldown = 10.0;

		ent->myskills.abilities[BLESS].delay = level.time + cooldown;

		//Change the curse think to the bless think
		slot = que_findtype(target->curses, NULL, BLESS);
		if (slot)
		{
			slot->ent->think = Bless_think;
			slot->ent->nextthink = level.time + FRAMETIME;
		}

		//Notify the target
		if (target == ent)
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration);
		}
		else if ((target->client) && !(target->svflags & SVF_MONSTER))
		{
			gi.cprintf(target, PRINT_HIGH, "YOU HAVE BEEN BLESSED FOR %0.1f seconds!!\n", duration);
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->myskills.player_name, duration);
		}
		else
		{
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s for %0.1f seconds.\n", target->classname, duration);
		}
		//Play the spell sound!
		gi.sound(target, CHAN_ITEM, gi.soundindex("curses/bless.wav"), 1, ATTN_NORM, 0);
	}
}
Пример #12
0
void Cmd_Deflect_f(edict_t *ent)
{
	float duration;
	edict_t *target = ent; // default target is self

	if (!V_CanUseAbilities(ent, DEFLECT, DEFLECT_COST, true))
		return;

	duration = DEFLECT_INITIAL_DURATION + DEFLECT_ADDON_DURATION * ent->myskills.abilities[DEFLECT].current_level;

	// bless the tank instead of the noclipped player
	if (PM_PlayerHasMonster(ent))
		target = target->owner;

	//Blessing self?
	if (Q_strcasecmp(gi.argv(1), "self") == 0)
	{
		if (!curse_add(target, ent, DEFLECT, 0, duration))
		{
			gi.cprintf(ent, PRINT_HIGH, "Unable to bless self.\n");
			return;
		}
		//target = ent;
	}
	else
	{
		target = curse_Attack(ent, DEFLECT, 512.0, duration, false);
	}

	if (target != NULL)
	{
		que_t *slot = NULL;

		//Finish casting the spell
		ent->client->ability_delay = level.time + DEFLECT_DELAY;
		ent->client->pers.inventory[power_cube_index] -= DEFLECT_COST;
	//	ent->myskills.abilities[DEFLECT].delay = level.time + duration + DEFLECT_DELAY;

		//Change the curse think to the deflect think
		slot = que_findtype(target->curses, NULL, DEFLECT);
		if (slot)
		{
			slot->ent->think = deflect_think;
			slot->ent->nextthink = level.time + FRAMETIME;
			slot->ent->random = DEFLECT_INITIAL_PROJECTILE_CHANCE+DEFLECT_ADDON_HITSCAN_CHANCE*ent->myskills.abilities[DEFLECT].current_level;
			if (slot->ent->random > DEFLECT_MAX_PROJECTILE_CHANCE)
				slot->ent->random = DEFLECT_MAX_PROJECTILE_CHANCE;
		}

		//Notify the target
		if (target == ent)
		{
			gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n", duration);
		}
		else if ((target->client) && !(target->svflags & SVF_MONSTER))
		{
			gi.cprintf(target, PRINT_HIGH, "You have been blessed with deflect for %0.1f seconds!\n\n", duration);
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", target->myskills.player_name, duration);
		}
		else
		{
			gi.cprintf(ent, PRINT_HIGH, "Blessed %s with deflect for %0.1f seconds.\n", V_GetMonsterName(target), duration);
		}

		//Play the spell sound!
		gi.sound(target, CHAN_ITEM, gi.soundindex("curses/prayer.wav"), 1, ATTN_NORM, 0);
	}
}