Lol, you wanna take a look at it? Might as well put it up, but I warn you, it's very slow. Almost to the point of being ridiculous and unusable. Actually it probably is unusable considering how few bullets it can handle.
Anyway, I present to you all, the ObjectShotA.
/************************************************************
*
* Constants
*
***********************************************************/
let OBJ_ID = 0;
let OBJ_START_FRAME = 1;
let OBJ_CURRENT_BEHAVIOR = 2;
let BEHAVIOR_DURATION = 0;
let BEHAVIOR_VELOCITY = 1;
let BEHAVIOR_ANGLE = 2;
let BEHAVIOR_ANGULAR_VELOCITY = 3;
let BEHAVIOR_ACCELERATION = 4;
let BEHAVIOR_MAX_MIN_SPEED = 5;
let BEHAVIOR_GRAPHIC = 6;
let MAX_BEHAVIOR_COUNT = 8;
/************************************************************
*
* Variables
*
***********************************************************/
let BehaviorShots = [];
let BehaviorShotBehaviors = [];
/************************************************************
*
* Public Functions
*
***********************************************************/
function CreateObjectShotA(x, y, delay, behavior){
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x, y);
ObjShot_SetDelay(obj, delay);
let startFrame = CurrentFrame();
//id, starting frame, current behavior, behavior list
let behaviorShot = [obj, startFrame, 0];
let len = length(behavior);
let behaviorShotBehavior = [];
if(len < MAX_BEHAVIOR_COUNT){
behaviorShotBehavior = behaviorShotBehavior ~ behavior;
loop(MAX_BEHAVIOR_COUNT-len) {
behaviorShotBehavior = behaviorShotBehavior ~ [[-1, 0, 0, 0, 0, 0, 0]];
}
} else if (len > MAX_BEHAVIOR_COUNT){
ascent(i in 0..MAX_BEHAVIOR_COUNT) {
behaviorShotBehavior = behaviorShotBehavior ~ [behavior[i]];
}
}
BehaviorShots = BehaviorShots ~ [behaviorShot];
BehaviorShotBehaviors = BehaviorShotBehaviors ~ [behaviorShotBehavior];
return obj;
}
function ObjectShotA_Run(){
let len = length(BehaviorShots);
OutputDebugString(0, "len", len);
descent(i in 0..len){
if(Obj_BeDeleted(BehaviorShots[i][OBJ_ID])){
BehaviorShots = erase(BehaviorShots, i);
BehaviorShotBehaviors = erase(BehaviorShotBehaviors, i);
}
else{
let behaviorShot = BehaviorShots[i];
let behaviorShotBehavior = BehaviorShotBehaviors[i];
BehaviorShot_updateState(behaviorShot, behaviorShotBehavior);
BehaviorShot_updateAttributes(behaviorShot, behaviorShotBehavior);
}
}
}
/************************************************************
*
* Private Functions
*
***********************************************************/
function BehaviorShot_updateAttributes(behaviorShot, behaviorShotBehavior){
let obj = behaviorShot[OBJ_ID];
let behaviors = behaviorShotBehavior;
let currentBehaviorIndex = behaviorShot[OBJ_CURRENT_BEHAVIOR];
let currentBehavior = behaviors[currentBehaviorIndex];
let angularVelocity = currentBehavior[BEHAVIOR_ANGULAR_VELOCITY];
let acceleration = currentBehavior[BEHAVIOR_ACCELERATION];
let maxMinSpeed = currentBehavior[BEHAVIOR_MAX_MIN_SPEED];
let speed = Obj_GetSpeed(obj);
let angle = Obj_GetAngle(obj);
let newSpeed = speed + acceleration;
if((acceleration > 0 && newSpeed > maxMinSpeed) || (acceleration < 0 && newSpeed < maxMinSpeed)){
newSpeed = maxMinSpeed;
}
let newAngle = angle + angularVelocity;
Obj_SetSpeed(obj, newSpeed);
Obj_SetAngle(obj, newAngle);
}
function BehaviorShot_updateState(behaviorShot, behaviorShotBehavior){
let obj = behaviorShot[OBJ_ID];
let startFrame = behaviorShot[OBJ_START_FRAME];
let timePassed = CurrentFrame() - startFrame;
let behaviors = behaviorShotBehavior;
let o = BehaviorShot_getBehaviorShotIndex(obj);
let len = length(behaviors);
descent(i in 0..len){
let behavior = behaviors[i];
let triggerTime = behavior[BEHAVIOR_DURATION];
if( triggerTime >= 0 && timePassed - triggerTime == 0){
BehaviorShot_setBehavior(obj, behavior);
BehaviorShots[o] = [obj, startFrame, i];
}
}
}
function BehaviorShot_setBehavior(obj, behavior){
let speed = behavior[BEHAVIOR_VELOCITY];
let angle = behavior[BEHAVIOR_ANGLE];
let graphic = behavior[BEHAVIOR_GRAPHIC];
if(speed != NULL){
Obj_SetSpeed(obj, speed);
}
if(angle != NULL){
Obj_SetAngle(obj, angle);
}
ObjShot_SetGraphic(obj, graphic);
}
function BehaviorShot_getBehaviorShotIndex(obj){
let len = length(BehaviorShots);
ascent(i in 0..len){
let behaviorShot = BehaviorShots[i];
if(behaviorShot[OBJ_ID]== obj){
return i
}
}
return -1
}
function BehaviorShot_getBehaviorShot(obj){
let len = length(BehaviorShots);
ascent(i in 0..len){
let behaviorShot = BehaviorShots[i];
if(behaviorShot[OBJ_ID]== obj){
return behaviorShot;
}
}
RaiseError("Can't find obj.", "BehaviorShot Error");
}
function BehaviorShot_getBehaviorShotBehavior(obj){
let len = length(BehaviorShots);
ascent(i in 0..len){
let behaviorShot = BehaviorShots[i];
if(behaviorShot[OBJ_ID]== obj){
return BehaviorShotBehaviors[i];
}
}
RaiseError("Can't find obj.", "BehaviorShot Error");
}
function debugShot(obj, i){
let behaviorShot = BehaviorShot_getBehaviorShot(obj);
let behaviorShotBehavior = BehaviorShot_getBehaviorShotBehavior(obj);
OutputDebugString(1, "obj", obj);
OutputDebugString(2, "OBJ_START_FRAME", behaviorShot[OBJ_START_FRAME]);
OutputDebugString(3, "OBJ_CURRENT_BEHAVIOR", behaviorShot[OBJ_CURRENT_BEHAVIOR]);
debugBehavior(behaviorShotBehavior[i]);
}
function debugBehavior(b){
OutputDebugString(4, "BEHAVIOR_DURATION", b[BEHAVIOR_DURATION]);
OutputDebugString(5, "BEHAVIOR_VELOCITY", b[BEHAVIOR_VELOCITY]);
OutputDebugString(6, "BEHAVIOR_ANGLE", b[BEHAVIOR_ANGLE]);
OutputDebugString(7, "BEHAVIOR_ANGULAR_VELOCITY", b[BEHAVIOR_ANGULAR_VELOCITY]);
OutputDebugString(8, "BEHAVIOR_ACCELERATION", b[BEHAVIOR_ACCELERATION]);
OutputDebugString(9, "BEHAVIOR_MAX_MIN_SPEED", b[BEHAVIOR_MAX_MIN_SPEED]);
OutputDebugString(10, "BEHAVIOR_GRAPHIC", b[BEHAVIOR_GRAPHIC]);
}
To use, put it in your lib folder and include it in whatever scripts are gonna use it. Put ObjectShotA_Run(); in your @MainLoop where it will be run once per frame. The parameters are rather scary but if you think of it differently, it's actually rather similar to setting up regular ShotAs
#TouhouDanmakufu
#Title[Test]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main
{
#include_function ".\BehaviorShot.dnh"
let frame = 0;
@Initialize
{
SetLife(1);
}
@MainLoop
{
if (frame == 60){
CreateBehaviorShot(GetCenterX, GetCenterY, 10, [
[0, 5, 90, 4, -0.1, 1, 1],
[30, NULL, NULL, -1, 0, 0, 1],
[60, NULL, NULL, 0, 0.01, 3, 1]
]);
}
BehaviorShot_Run();
frame++;
}
@Finalize
{
}
@DrawLoop
{
}
}
As you can see, you don't need a FireShot(); as it is fired automatically for you when you call that one function. The parameters for the function are as follows:
CreateObjectShotA(starting_x, starting_y, delay, [
[time_to_modify_behavior, speed, angle, angular_velocity, acceleration, max/min_speed, graphic]
]);
You can have up to 8 of those arrays inside the main array which correspond to up to 8 SetShotDataA functions. Don't forget the commas between the array elements in the big array.
Feel free to try to optimize this. This was the best I could do without killing Danmakufu or myself.