Archives des forums MMO/MMORPG > Neverwinter Nights > NWN - Maskado > L'artillerie ?
L'artillerie ?
Par Hiztaar le 16/12/2002 à 20:54:07 (#2807004)
Voilà c'est le Challenge :)
Par Jedaï le 17/12/2002 à 13:00:12 (#2812181)
Par contre pour les invocations d'armes de siège, c'est assez facile : tu crée un item particulier (tag : "SIEGEBABY") et tu met un script sur le OnUnaquireItem du module qui va créer ta baliste à la place lorsqu'on le posera sur le sol ! Ensuite on pourra ramasser la baliste en l'utilisant (avec la baliste vivante ça ne posera pas problème sinon tu n'as qu'à faire un dialogue pour donner les ordres avec une option pour la ramasser). Evidemment ramasser une baliste c'est pas le summum du réalisme, mais l'invoquer non plus.:mdr:
Par Jaha Effect le 18/12/2002 à 5:10:53 (#2819564)
//::///////////////////////////////////////////////
//:: Ballista
//:: tg_ballista
//:://////////////////////////////////////////////
/* Placed in On_Use script for ballista object.
The ballista object must be marked usable.
Creates a cone shape designated as a "field of view".
Cycles through hostile creatures in the area, and
checks if it is safe to fire upon them.
Fires a bolt that does area of effect damage.
Purpose: Wrote the script to automate NPCs to use Ballistas to
add flavor to a scenario where the PC's are involved in small battles and sieges.
*/
//:://////////////////////////////////////////////
//:: Created By: Chakar
//:: Created On: 6/24/2002
//:: Lastmodified On: 6/27/2002
//:: Version: 1.1 Broke Script into seperate functions for readability
//:: Version: 1.2 Added comments for distribution.
//:: Version: 1.3 Fixed Vector bug
//:: Now using target creature as center of effect.
//:: Version: 1.4 Saving throw now checked with: GetReflexAdjustedDamage
//:: Replaced reputation checks with GetIsEnemy()
//:: Added LoS check. (was shooting through walls).
//:: Added Delay before applying damage to better match bolt impact.
//::Version 1.5 Fixed bug caused by GetFacing returning incorrect information for
//:: heading between 180 and 360, now using GetFacingFromLocation.
//::
//:: Do some additional geometric checks to ensure object set by AcquireTarget
//:: is from the specified area as described.
//:://////////////////////////////////////////////
//State Constants
int ST_READY = 100;
int ST_RELOAD = 110;
int ST_RELOADING = 120;
//Function Declarations
void ReloadBallista(object oUser);
int CheckAngleToTarget(object oTarget, float fAngle, float fOrientation);
int AcquireTarget(object oUser);
void ApplyDamage();
int GetIsAcceptableTarget(object oUser, object oTarget);
//Variables.. change these to set damage and field of view.
float fMaxRange = 40.0f; //Max Range
float fMinRange = 5.0f; //Min Range
float fWidth = 40.0f; //Radius of cone at widest point
int iDC = 10; //Difficulty check(reflex save for half damage)
float fSize = 5.0f; //Radius of damage area
int iDice = 6; //Number of dice to roll for damage (currently d8s, changeable in code)
void main()
{
//Checks to see if the Ballista has been initialized
if (!GetLocalInt(OBJECT_SELF, "iInitialized"))
{
SetLocalInt(OBJECT_SELF, "iInitialized", 1);
SetLocalInt(OBJECT_SELF, "iState", ST_READY);
}
int iState = GetLocalInt(OBJECT_SELF,"iState");
object oTarget;
object oUser;
oUser = GetLastUsedBy();
switch(iState)
{
case 100: //Ready
if (AcquireTarget(oUser))
{
ApplyDamage();
if (GetIsPC(oUser))
SendMessageToPC(oUser,"Fired at " + GetLocalString(OBJECT_SELF, "sTarget"));
}
break;
case 110: //Reload
if (GetIsPC(oUser))
{
SendMessageToPC(oUser, "Reloading Ballista");
}
SetLocalInt(OBJECT_SELF, "iState", ST_RELOADING);
ActionWait(6.0); //Reload Time in Seconds
AssignCommand(oUser,PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,6.0));
ActionDoCommand(ReloadBallista(oUser));
break;
case 120: //Reloading
break;
}
}
void ReloadBallista(object oUser)
{
switch (GetIsPC(oUser))
{
case TRUE://If User is a PC, send reload messages.
{
if ((!GetIsInCombat(oUser)) && (GetDistanceToObject(oUser) < 2.5))
{
SendMessageToPC(oUser, "Ballista Reloaded");
SetLocalInt(OBJECT_SELF, "iState", ST_READY);
}
else
{
SendMessageToPC(oUser, "Reloading Interrupted");
SetLocalInt(OBJECT_SELF, "iState", ST_RELOAD);
}
break;
}
case FALSE:
{
if ((!GetIsInCombat(oUser)) && (GetDistanceToObject(oUser) fMinRange && GetDistanceBetween(oTarget, OBJECT_SELF) 0)
DelayCommand(fDelay,ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
oTarget = GetNextObjectInShape(SHAPE_SPHERE, fSize, lTarget, TRUE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
}
SetLocalInt(OBJECT_SELF, "iState", ST_RELOAD);
}
//Set Conditions for firing here. Current condition is that there are more
// enemies than friends in target damage area.
int GetIsAcceptableTarget(object oUser, object oTarget)
{
object oPotentialVictim;
int iFriends = 0;
int iEnemies = 0;
oPotentialVictim = GetFirstObjectInShape(SHAPE_SPHERE, fSize, GetLocation(oTarget), TRUE, OBJECT_TYPE_CREATURE);
while (GetIsObjectValid(oPotentialVictim))
{
if (GetIsEnemy(oTarget, oUser))
iEnemies += 1;
else
iFriends += 1;
oPotentialVictim = GetNextObjectInShape (SHAPE_SPHERE, fSize, GetLocation(oTarget), TRUE, OBJECT_TYPE_CREATURE);
}
if (iEnemies > iFriends)
return 1;
else
return 0;
}
//The GetObjectInShape functions were returning objects that would not be in the shape
//as I envisioned it. (Specifically, it was returning objects from the ballista's right hand side,
//which were way out of the range of the cone.. this checks to make sure they are with in range of the cone
int CheckAngleToTarget(object oTarget, float fAngle, float fOrientation)
{
vector vBallista;
vector vTarget;
float fTargetAngle;
float fHyp;
float fRightHeading;
float fLeftHeading;
vBallista = GetPosition(OBJECT_SELF);
vTarget = GetPosition(oTarget);
vTarget.x = vTarget.x - vBallista.x ;
vTarget.y = vTarget.y - vBallista.y ;
fHyp = sqrt(pow(vTarget.x, 2.0) + pow(vTarget.y, 2.0));
fTargetAngle = asin((vTarget.y / fHyp));
if (vTarget.x < 0.0)
{
if(vTarget.y 0.0)
{
fTargetAngle = 180.0 - fTargetAngle;
}
else
{
fTargetAngle = 180.0;
}
}
else if (vTarget.x > 0.0)
{
if (vTarget.y 0.0)
{
fTargetAngle = 0.0 + fTargetAngle;
}
else
{
fTargetAngle = 360.0;
}
}
else
{
if (vTarget.y > 0.0)
{
fTargetAngle = 90.0;
}
else if (vTarget.y 360.0)
{
fRightHeading -= 360.0;
}
else if (fRightHeading == 360.0)
fRightHeading = 0.0;
if (fLeftHeading > 360.0)
fLeftHeading -= 360.0;
else if (fLeftHeading == 0.0)
fLeftHeading == 360.0;
if (fTargetAngle > 360.0)
fTargetAngle -= 360.0;
if (fTargetAngle >= fRightHeading && fTargetAngle <= fLeftHeading)
{
PrintString("Angle within range");
return 1;
}
else
return 0;
}
et j'ai déjà testé ça marche :)
JOL Archives 1.0.1
@ JOL / JeuxOnLine