ScarletBlackMarket/player/Chimata/Chimata_Main.dnh

737 lines
20 KiB
Plaintext
Raw Normal View History

#TouhouDanmakufu[Player]
#ScriptVersion[3]
#ID["Chimata"]
#Title["Chimata Tenkyuu"]
#Text["Shot Type: Blank Card Set[r]Spell Card: Shield of Market Regulation"]
//#Image["./mariremi_lib/mariremi_illust.png"]
#ReplayName["Chimata"]
#include "script/KevinSystem/Kevin_PlayerLib.txt"
#include "script/KevinSystem/PlayerSoundLib.dnh"
#include "./Chimata_Function.dnh"
#include "./Chimata_ShotConst.dnh"
#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt"
#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt"
let csd = GetCurrentScriptDirectory();
// Global Variables
float maxX = GetStgFrameWidth();
float maxY = GetStgFrameHeight();
// Images & Sound
let teamimg = csd ~ "./playerlib/Chimata_Sheet.png";
LoadTextureEx(teamimg, true, true);
//ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR);
let sndpath = csd ~ "./sound";
// Other stuff
float playerX = 0;
float playerY = 0;
let objPlayer = GetPlayerObjectID();
int plrender = Obj_GetRenderPriorityI(objPlayer);
bool ripplayer = false;
float shotspeed = 0;
float bombrand = 0;
bool bombenable = false;
bool focusactive = false;
bool ishoming = false;
int[] _enemyArray = []; // Prepare an array to store enemy IDs for Kouda's homing shot
int[] _existArray = [];
int[] _shotArray = [];
int grazecounter = 0; // For basic graze = PIV mechanic
float[] PlayerSpd = [10, 5.35];
// Custom events for scoring mechanic
const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons
const EV_PIV_250 = EV_USER + 101i; // Spells
const EV_PIV_500 = EV_USER + 102i; // Last Spells
const EV_PIV_2000 = EV_USER + 103i; // What.
@Initialize{
if(!IsCommonDataAreaExists("PIV")){
CreateCommonDataArea("PIV");
SetAreaCommonData("PIV", "currentvalue", 10000);
}
else{}
SetPlayerStateEndEnable(true);
// Stuff
parameterrender();
playerrender();
Obj_SetRenderPriorityI(objPlayer, 43);
plrender = Obj_GetRenderPriorityI(objPlayer);
_SoundTask();
//SetIntersectionVisualization(true); // Debug
_Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 5, 2, 80);
_HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 1280, 512, 1408, 640, 1536, 896, 2048, 1408, 0.3, 0.65);
SetShotAutoDeleteClip(256, 256, 256, 256);
// Shot functions
//_CAVELaser();
_ShotType();
//UniversalAlphaHandle(_shotArray);
// Shot data loading
LoadPlayerShotData(csd ~ "./Chimata_ShotData.dnh");
}
@MainLoop{
_enemyArray = GetIntersectionRegistedEnemyID;
shotspeed += 1; // Managing the shot rate
//_shotArray = GetAllShotID(TARGET_PLAYER);
//UniversalAlphaHandle(_shotArray);
playerX = ObjMove_GetX(objPlayer);
playerY = ObjMove_GetY(objPlayer);
yield;
}
@Event{
alternative(GetEventType)
// Delete effect
case(EV_DELETE_SHOT_PLAYER){
let graphic = GetEventArgument(2);
float[] position = GetEventArgument(1);
let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0)), 0, 99999, graphic);
ObjShot_SetIntersectionEnable(obj, false); _DeleteEffect(obj);
//if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);}
//else{_DeleteEffect(obj);}
}
// PIV-item spawning events
case(EV_PIV_100){
let arg = GetEventArgument(0);
CreatePIVItem(PIV_100, arg[0], arg[1]);
}
case(EV_PIV_250){
let arg = GetEventArgument(0);
CreatePIVItem(PIV_250, arg[0], arg[1]);
}
case(EV_PIV_500){
let arg = GetEventArgument(0);
CreatePIVItem(PIV_500, arg[0], arg[1]);
}
// Basic functionality events
case(EV_REQUEST_SPELL){
let bomb = GetPlayerSpell();
if (bomb >= 1){
SetScriptResult(true);
SetPlayerSpell(bomb - 1);
_Bomb();
_SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame());
}
else {
SetScriptResult(false);
}
}
case(EV_HIT){
ObjSound_Play(predeathsfx);
_DeathbombWarning(teamimg, [1536, 384, 1536+512, 384+512], 15, 0.75);
}
case(EV_PLAYER_SHOOTDOWN){
ObjSound_Play(deathsfx);
ripplayer = true;
_SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 120);
}
case(EV_PLAYER_REBIRTH){
ripplayer = false;
SetPlayerInvincibilityFrame(180);
_SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150);
SetPlayerSpell( max(2,GetPlayerSpell()) );
}
case(EV_GRAZE){
grazecounter += GetEventArgument(0);
ObjSound_Play(grazesfx);
while(grazecounter >= 10){
SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10);
grazecounter -= 10;
}
}
}
@Finalize{
}
// Homing
task _HomeShot(int option_) {
int shot_ = 0;
float duration = 1;
float durationOption = 99999;
bool homingBool = false;
float basepenetrate = ObjShot_GetPenetration(shot_);
float basedmg = ObjShot_GetDamage(shot_);
//
for (int t = 0i; t < durationOption && !Obj_IsDeleted(option_); t++) {
// Checks if enemies are on screen. If enemies are visible, enable homing for the shots.
// _enemyArray is an array containing all enemy IDs, and is constantly updated in @MainLoop.
if (0 < length(_enemyArray)) {
float targetDist = 2000; // Arbitrary number (???)
int targetID = 0;
// Checks distance of every enemy on screen.
for each (int enemy in ref _enemyArray) {
float enemyX = ObjMove_GetX(enemy);
float enemyY = ObjMove_GetY(enemy);
if (0 < enemyX && enemyX < maxX && 0 < enemyY && enemyY < maxY) {
// Returns the hypotenuse of the triangle formed by the x & y distances between the shot and the enemy.
float shotDist = hypot(enemyX - ObjMove_GetX(objPlayer), enemyY - ObjMove_GetY(objPlayer));
// Locks the shot onto the enemy.
if (shotDist < targetDist) {
targetDist = shotDist;
targetID = enemy;
homingBool = true;
}
}
}
// Code to handle the actual homing.
if (homingBool) {
for (int f = 0; t < durationOption && !Obj_IsDeleted(option_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE; t++) {
ObjShot_SetAutoDelete(option_, false);
float shotAngle = NormalizeAngle(ObjMove_GetAngle(option_)); // Angle of the player shot
float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(option_), ObjMove_GetX(targetID) - ObjMove_GetX(option_))); // Returns angle from the shot to the enemy.
float angleDistance = AngularDistance(shotAngle, targetAngle); // Angular distance between enemy and player shot
float homeRate = Interpolate_Decelerate(0, 0.75, min(15, f) / 15);
// Homing speed?
ObjMove_SetAngle(option_, Interpolate_Decelerate(shotAngle, shotAngle + angleDistance, homeRate)); // Interpolate_Necko
f++;
yield;
}
}
/*if (homingBool) {
for (int f = 0; t < duration && !Obj_IsDeleted(shot_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && !ObjCol_IsIntersected(shot_); t++) {
ObjShot_SetAutoDelete(shot_, false);
float shotAngle = NormalizeAngle(ObjMove_GetAngle(shot_)); // Angle of the player shot
float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(shot_), ObjMove_GetX(targetID) - ObjMove_GetX(shot_))); // Returns angle from the shot to the enemy.
float angleDistance = AngularDistance(shotAngle, targetAngle); // Angular distance between enemy and player shot
float homeRate = Interpolate_Decelerate(0, 0.75, min(60, f) / 60);
// Homing speed?
ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, 1)); // Interpolate_Necko
f++;
yield;
}
ObjShot_SetAutoDelete(shot_, true);
ObjMove_SetAngularVelocity(shot_, 0);
homingBool = false;
}*/
}
yield;
}
}
task _SwingBehaviour(target){
float ang = 0;
Obj_SetRenderPriorityI(target, 42);
while(true){
ObjRender_SetAngleZ(target, 0+20*sin(ang));
ang += 360/120;
yield;
}
}
task _ShotType(){
// Offsets for 4 front options
// Alternative player option function
function PlayerOption(
float offsetx, float offsety,
texture,
int left, int top, int right, int bottom, float scale,
int width, int animdelay, int frameno, bool triggeranimation,
bool triggerspin, float spinspeed,
bool onlyFocus, bool onlyUnfocus
){
// IMPORTANT!
let option = ObjShot_Create(OBJ_SHOT);
ObjShot_Regist(option);
ObjShot_SetAutoDelete(option, false);
ObjShot_SetGraphic(option, 3);
ObjShot_SetPenetration(option, 9999^9999);
ObjShot_SetDamage(option, 0);
ObjShot_SetIntersectionEnable(option, false);
ObjMove_SetAngle(option, 270);
//
bool visible;
int animate = 0;
float optx;
float opty;
ObjRender_SetScaleXYZ(option, scale);
ObjRender_SetBlendType(option, BLEND_ALPHA);
ObjRender_SetAlpha(option, 225);
Obj_SetRenderPriorityI(option, 41);
ObjRender_SetPosition(option, offsetx, offsety, 1);
// Animation
async{
while(triggeranimation){
ObjSprite2D_SetSourceRect(option, left+width*floor(animate/animdelay), top, right+width*floor(animate/animdelay)-1, bottom-1);
animate++;
if (animate >= animdelay*frameno){animate = 0;}
yield;
}
}
// Rotation
async{
float i = 0;
while(triggerspin){
//ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1);
ObjRender_SetAngleZ(option, i);
i += spinspeed;
yield;
}
}
// Follow
async{
while(true){
ObjMove_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety);
yield;
}
}
// Visibility
async{
// Always visible
if((onlyFocus && onlyUnfocus) || (!onlyFocus && !onlyUnfocus)) {
loop
{
if(GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
yield;
}
}
// Visible when focused only
else if(onlyFocus && !onlyUnfocus){
loop
{
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
yield;
}
}
// Visible when unfocused only
else if(!onlyFocus && onlyUnfocus){
loop
{
if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;}
else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;}
yield;
}
}
}
function _FadeIn(){
ascent(i in 0..15){
ObjRender_SetAlpha(option, Interpolate_Decelerate(0, 225, i/15));
yield;
}
}
function _FadeOut(){
ascent(i in 0..15){
ObjRender_SetAlpha(option, Interpolate_Decelerate(225, 0, i/15));
yield;
}
}
return option;
}
float offsetX1 = 125;
float offsetX2 = offsetX1 * 2;
float offsetY1 = 75;
// Array that contains static/unchanging values for the PlayerOption
let val = [0, 512, 256, 768, 0.3, 256, 1, 1, false, false, 0, true, true];
// Option handling (right -> rightmost -> left -> leftmost)
float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]];
int opt1 = PlayerOption(
offsetArray[0][0], offsetArray[0][1],
teamimg,
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8],
val[9], val[10],
val[11], val[12]);
int opt2 = PlayerOption(
offsetArray[1][0], offsetArray[1][1],
teamimg,
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8],
val[9], val[10],
val[11], val[12]);
int opt3 = PlayerOption(
offsetArray[2][0], offsetArray[2][1],
teamimg,
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8],
val[9], val[10],
val[11], val[12]);
int opt4 = PlayerOption(
offsetArray[3][0], offsetArray[3][1],
teamimg,
val[0], val[1], val[2], val[3], val[4],
val[5], val[6], val[7], val[8],
val[9], val[10],
val[11], val[12]);
int[] optArray = [opt1, opt2, opt3, opt4];
_HomingStars(optArray[0], 0); _HomeShot(optArray[0]);
_HomingStars(optArray[1], 1); _HomeShot(optArray[1]);
_HomingStars(optArray[2], 2); _HomeShot(optArray[2]);
_HomingStars(optArray[3], 3); _HomeShot(optArray[3]);
task _HomingStars(option, value){
loop{
if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){
async{
if(value == 0){
ascent(i in 0..15){
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15));
yield;
}
}
else if(value == 1){
ascent(i in 0..15){
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*2, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15));
yield;
}
}
else if(value == 2){
ascent(i in 0..15){
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15));
yield;
}
}
else if(value == 3){
ascent(i in 0..15){
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*2, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15));
yield;
}
}
}
async{
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){
if(shotspeed % 5 == 0){
float x = ObjRender_GetX(option);
float y = ObjRender_GetY(option);
ascent(i in -1..1){
let shotA = CreatePlayerShotA1(-50+x+25-50*i, y, 50, ObjMove_GetAngle(option), 2, 1.1, 2);
_BulletRescalePlayer(shotA, 0.7, true, 1);
ObjRender_SetAlpha(shotA, 255*(universalAlpha/100));
Obj_SetRenderPriorityI(shotA, 39);
ObjSound_Play(basesfx);
}
}
}
}
}
else{
async{
if(value == 0){
ascent(i in 0..15){
ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 275, i/15));
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*0.45, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15));
yield;
}
}
else if(value == 1){
ascent(i in 0..15){
ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 295, i/15));
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*0.75, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15));
yield;
}
}
else if(value == 2){
ascent(i in 0..15){
ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 265, i/15));
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*0.45, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15));
yield;
}
}
else if(value == 3){
ascent(i in 0..15){
ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 245, i/15));
ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*0.75, i/15));
ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15));
yield;
}
}
}
async{
if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){
if(shotspeed % 5 == 0){
float x = ObjRender_GetX(option);
float y = ObjRender_GetY(option);
ascent(i in -1..1){
let shotA = CreatePlayerShotA1(-50+x+25-50*i, y, 50, ObjMove_GetAngle(option), 2.6, 1.1, 1);
_BulletRescalePlayer(shotA, 0.7, true, 1);
ObjRender_SetAlpha(shotA, 255*(universalAlpha/100));
Obj_SetRenderPriorityI(shotA, 39);
ObjSound_Play(basesfx);
}
}
}
}
}
yield;
}
}
}
// Basic player parameters
task parameterrender(){
SetPlayerItemScope(120);
SetPlayerLife(9); // Debug
SetPlayerSpell(2);
SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0)
SetPlayerRebirthFrame(12);
SetPlayerAutoItemCollectLine(GetStgFrameHeight/3);
SetPlayerRebirthLossFrame(0);
ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 1.25, 40);
}
// Renders the shottype
// Player sprites
task playerrender(){
// Why is this movement code so cursed jesus fucking christ
float scale = 0.32; // Scalies
int frame = 0;
ObjPrim_SetTexture(objPlayer, teamimg);
ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 400, 400);
ObjSprite2D_SetDestCenter(objPlayer);
Obj_SetRenderPriorityI(objPlayer, 42);
ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1);
// Lower "speed" parameter = FASTER SPEED
// FOR WHEN ONLY IDLE SPRITES ARE DONE
loop{
frame++;
_RenderPlayerMovement(objPlayer, frame, 0, 0, 400, 400, scale, 4, 6);
if (frame >= (5*4-1)){frame = 0;}
yield;
}
}
task PointblankPlacebo(target, scale, multiplier){
int len = 10;
while(GetObjectDistance(target, objPlayer) < 90){
_BulletRescalePlayer(target, scale*multiplier, true, multiplier); // Pointblank
yield;
}
ascent(i in 0..len){
_BulletRescalePlayer(target, Interpolate_Decelerate(scale*multiplier, scale, i/len), true, Interpolate_Decelerate(multiplier, 1, i/len));
yield;
}
}
task Fadein(target, len){
ascent(i in 0..len){
_BulletRescalePlayer(target, Interpolate_Decelerate(0.4, 0.7, i/len), true, Interpolate_Decelerate(0.4, 0.7, i/len));
//ObjRender_SetBlendType(target, BLEND_ADD_ARGB);
yield;
}
ObjRender_SetBlendType(target, BLEND_ALPHA);
}
task Fadein(target, len, targetscale, targetscalehitbox){
ascent(i in 0..len){
_BulletRescalePlayer(target, Interpolate_Decelerate(0.1, targetscale, i/len), true, Interpolate_Decelerate(1, targetscalehitbox, i/len));
//ObjRender_SetBlendType(target, BLEND_ADD_ARGB);
yield;
}
ObjRender_SetBlendType(target, BLEND_ALPHA);
}
// Handling of bomb
task _Bomb(){
// Preparation
SetForbidPlayerShot(true);
SetForbidPlayerSpell(true);
SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45);
// Spell object
let manageObj = GetSpellManageObject(); // SPELL BEGINS
ObjSpell_Regist(manageObj);
ObjSound_Play(bombsfx);
SetPlayerSpeed(PlayerSpd[0]*1.5, PlayerSpd[0]*1.5);
int hakkero = CreatePlayerShotA1(playerX, playerY, 0, 0, 12, 999999, 4);
ObjShot_SetIntersectionEnable(hakkero, true);
ObjShot_SetEraseShot(hakkero, true);
ObjShot_SetSpellFactor(hakkero, true);
async{
ascent(i in 0..45){
_BulletRescalePlayer(hakkero, Interpolate_Decelerate(0.1, 1, i/45), true, 1);
ObjRender_SetAlpha(hakkero, Interpolate_Decelerate(0, 255, i/45));
yield;
}
}
ascent(i in 0..240){
ObjMove_SetPosition(hakkero, playerX, playerY);
yield;
}
// Cleanup, end of spell
ObjShot_FadeDelete(hakkero);
SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]);
SetForbidPlayerShot(false);
wait(60);
SetForbidPlayerSpell(false);
Obj_Delete(manageObj); // !!! IMPORTANT !!!
}
// Screenshake function for bomb's duration - adapted from Sparen's tutorials
task _BombShake(shaketime, intensity){
float baseintensity = intensity;
float shakeno = shaketime;
ascent(i in 0..shakeno){
Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity));
Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity));
intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno);
shaketime--;
yield;
}
while(shaketime > 0){yield;}
Set2DCameraFocusX(GetStgFrameWidth/2);
Set2DCameraFocusY(GetStgFrameHeight/2);
yield;
}