■全体構成(「※1」などで検索して飛んでみよう)
※1
※2
※3
■内容解説
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
#include(): Usage: (a-page-name-you-want-to-include[,title|,notitle])
void sapper_actorlimit_setup(CBlob@ this)
{
u16[] networkIDs; this.set("LimitedActors", networkIDs);
}
bool sapper_has_hit_actor(CBlob@ this, CBlob@ actor)
{
u16[]@ networkIDs; this.get("LimitedActors", @networkIDs); return networkIDs.find(actor.getNetworkID()) >= 0;
}
u32 sapper_hit_actor_count(CBlob@ this)
{
u16[]@ networkIDs; this.get("LimitedActors", @networkIDs); return networkIDs.length;
}
void sapper_add_actor_limit(CBlob@ this, CBlob@ actor)
{
this.push("LimitedActors", actor.getNetworkID());
}
void sapper_clear_actor_limits(CBlob@ this)
{
this.clear("LimitedActors");
}
void onInit(CBlob@ this)
{
SapperInfo sapper;
sapper.state = SapperStates::normal; sapper.slideTime = 0; sapper.tileDestructionLimiter = 0;
this.set("sapperInfo", @sapper);
this.set_f32("gib health", -3.0f); addShieldVars(this, SHIELD_BLOCK_ANGLE, 2.0f, 5.0f); sapper_actorlimit_setup(this); this.getShape().SetRotationsAllowed(false); this.getShape().getConsts().net_threshold_multiplier = 0.5f; this.Tag("player"); this.Tag("flesh");
this.addCommandID("get bomb");
this.push("names to activate", "keg");
this.set_u8("bomb type", 255); for (uint i = 0; i < bombTypeNames.length; i++) { this.addCommandID("pick " + bombTypeNames[i]); }
//centered on bomb select ※2 //this.set_Vec2f("inventory offset", Vec2f(0.0f, 122.0f)); //centered on inventory this.set_Vec2f("inventory offset", Vec2f(0.0f, 0.0f));
SetHelp(this, "help self action", "sapper", "$Jab$Jab $LMB$", "", 4); SetHelp(this, "help self action2", "sapper", "$Shield$Shield $KEY_HOLD$$RMB$", "", 4);
this.getCurrentScript().runFlags |= Script::tick_not_attached; this.getCurrentScript().removeIfTag = "dead";
}
void onSetPlayer(CBlob@ this, CPlayer@ player)
{
if (player !is null) { player.SetScoreboardVars("ScoreboardIconsMod.png", 3, Vec2f(16, 16)); } ※スコアボードに表示されるアイコン関係?
}
void onTick(CBlob@ this)
{
u8 knocked = getKnocked(this);
if (this.isInInventory()) return;
//sapper logic stuff ※3 //get the vars to turn various other scripts on/off RunnerMoveVars@ moveVars; if (!this.get("moveVars", @moveVars)) { return; }
SapperInfo@ sapper; if (!this.get("sapperInfo", @sapper)) { return; }
Vec2f pos = this.getPosition(); Vec2f vel = this.getVelocity(); Vec2f aimpos = this.getAimPos(); const bool inair = (!this.isOnGround() && !this.isOnLadder());
Vec2f vec;
const int direction = this.getAimDirection(vec); const f32 side = (this.isFacingLeft() ? 1.0f : -1.0f);
bool pressed_a1 = this.isKeyPressed(key_action1) && !this.hasTag("noLMB"); bool pressed_a2 = this.isKeyPressed(key_action2); bool walking = (this.isKeyPressed(key_left) || this.isKeyPressed(key_right));
const bool myplayer = this.isMyPlayer();
if (!this.hasTag("exploding")) if (pressed_a2) //Self detonate { SetupBomb(this, 120, 64.0f, 8.0f, 24.0f, 0.4f, true); }
if(sapper.throwtimer == 0){ if(sapper.cooldown == 0){ if (this.isKeyPressed(key_action1) && !this.hasTag("noLMB")) { sapper.throwtimer = 8; this.Tag("throwing_mine"); sapper.cooldown = 60; } } else { sapper.cooldown -= 1; } }
if(sapper.throwtimer == 1){ if (getNet().isServer()){ CBlob @blob = server_CreateBlob("minimine", this.getTeamNum(), this.getPosition()); blob.SetDamageOwnerPlayer(this.getPlayer()); Vec2f arrowVel = ((this.getPosition() + Vec2f(0.0f, -4.0f)) - (this.getAimPos() + Vec2f(0.0f, -4.0f))); arrowVel.Normalize(); arrowVel *= -6; blob.setVelocity(arrowVel); }
this.Untag("throwing_mine"); sapper.throwtimer -= 1; } else if(sapper.throwtimer != 0){ sapper.throwtimer -= 1; }
//with the code about menus and myplayer you can slash-cancel; ※4 //we'll see if sappers dmging stuff while in menus is a real issue and go from there if (knocked > 0)// || myplayer && getHUD().hasMenus()) { sapper.state = SapperStates::normal; sapper.slideTime = 0;
pressed_a1 = false; pressed_a2 = false; walking = false;
} else if (this.isKeyJustReleased(key_action2) || (this.isKeyJustReleased(key_action1) && !this.hasTag("noLMB")) || this.get_u32("sapper_timer") <= getGameTime()) { sapper.state = SapperStates::normal; }
//throwing bombs
if (myplayer) { // space
if (this.isKeyJustPressed(key_action3)) { CBlob@ carried = this.getCarriedBlob(); bool holding = carried !is null;// && carried.hasTag("exploding");
CInventory@ inv = this.getInventory(); bool thrown = false; u8 bombType = this.get_u8("bomb type"); if (bombType == 255) { SetFirstAvailableBomb(this); bombType = this.get_u8("bomb type"); } if (bombType < bombTypeNames.length) { for (int i = 0; i < inv.getItemsCount(); i++) { CBlob@ item = inv.getItem(i); const string itemname = item.getName(); if (!holding && bombTypeNames[bombType] == itemname) { if (bombType >= 2) { this.server_Pickup(item); client_SendThrowOrActivateCommand(this); thrown = true; } else { CBitStream params; params.write_u8(bombType); this.SendCommand(this.getCommandID("get bomb"), params); thrown = true; } break; } } }
if (!thrown) { client_SendThrowOrActivateCommand(this); SetFirstAvailableBomb(this); } } }
if (getNet().isServer()) { sapper_clear_actor_limits(this); }
}
void onDie(CBlob@ this)
{
SetupBomb(this, 120, 64.0f, 8.0f, 24.0f, 0.4f, true);
}
void onCommand(CBlob@ this, u8 cmd, CBitStream @params)
{
if (cmd == this.getCommandID("get bomb")) { const u8 bombType = params.read_u8(); if (bombType >= bombTypeNames.length) return;
const string bombTypeName = bombTypeNames[bombType]; this.Tag(bombTypeName + " done activate"); if (hasItem(this, bombTypeName)) { if (bombType == 0) { if (getNet().isServer()) { CBlob @blob = server_CreateBlob("bomb", this.getTeamNum(), this.getPosition()); if (blob !is null) { TakeItem(this, bombTypeName); this.server_Pickup(blob); } } } else if (bombType == 1) { if (getNet().isServer()) { CBlob @blob = server_CreateBlob("waterbomb", this.getTeamNum(), this.getPosition()); if (blob !is null) { TakeItem(this, bombTypeName); this.server_Pickup(blob); blob.set_f32("map_damage_ratio", 0.0f); blob.set_f32("explosive_damage", 0.0f); blob.set_f32("explosive_radius", 92.0f); blob.set_bool("map_damage_raycast", false); blob.set_string("custom_explosion_sound", "/GlassBreak"); blob.set_u8("custom_hitter", Hitters::water); } } } else { }
SetFirstAvailableBomb(this); } } else if (cmd == this.getCommandID("cycle")) //from standardcontrols { // cycle arrows u8 type = this.get_u8("bomb type"); int count = 0; while (count < bombTypeNames.length) { type++; count++; if (type >= bombTypeNames.length) type = 0; if (this.getBlobCount(bombTypeNames[type]) > 0) { this.set_u8("bomb type", type); if (this.isMyPlayer()) { Sound::Play("/CycleInventory.ogg"); } break; } } } else if (cmd == this.getCommandID("activate/throw")) { SetFirstAvailableBomb(this); } else { for (uint i = 0; i < bombTypeNames.length; i++) { if (cmd == this.getCommandID("pick " + bombTypeNames[i])) { this.set_u8("bomb type", i); break; } } }
}
f32 onHit(CBlob@ this, Vec2f worldPoint, Vec2f velocity, f32 damage, CBlob@ hitterBlob, u8 customData)
{
CPlayer@ player=this.getPlayer(); if(this.hasTag("invincible") || (player !is null && player.freeze)) { return 0; } if(Hitters::bomb == customData)return 0;
return damage; //no block, damage goes through
}
bool isSliding(SapperInfo@ sapper)
{
return (sapper.slideTime > 0 && sapper.slideTime < 45);
}
void onCollision(CBlob@ this, CBlob@ blob, bool solid, Vec2f normal, Vec2f point1)
{
//return if we didn't collide or if it's teamie if (blob is null || !solid || this.getTeamNum() == blob.getTeamNum()) { return; }
const bool onground = this.isOnGround(); if (this.getShape().vellen > SHIELD_KNOCK_VELOCITY || onground) { SapperInfo@ sapper; if (!this.get("sapperInfo", @sapper)) { return; }
//printf("sapper.stat " + sapper.state ); }
}
void pushForward(CBlob@ this, f32 normalForce, f32 pushingForce, f32 verticalForce)
{
f32 facing_sign = this.isFacingLeft() ? -1.0f : 1.0f ; bool pushing_in_facing_direction = (facing_sign < 0.0f && this.isKeyPressed(key_left)) || (facing_sign > 0.0f && this.isKeyPressed(key_right)); f32 force = normalForce;
if (pushing_in_facing_direction) { force = pushingForce; }
this.AddForce(Vec2f(force * facing_sign , verticalForce));
}
bool hasItem(CBlob@ this, const string &in name)
{
CBitStream reqs, missing; AddRequirement(reqs, "blob", name, "Bombs", 1); CInventory@ inv = this.getInventory();
if (inv !is null) { return hasRequirements(inv, reqs, missing); } else { warn("our inventory was null! SapperLogic.as"); }
return false;
}
void TakeItem(CBlob@ this, const string &in name)
{
CBlob@ carried = this.getCarriedBlob(); if (carried !is null) { if (carried.getName() == name) { carried.server_Die(); return; } }
CBitStream reqs, missing; AddRequirement(reqs, "blob", name, "Bombs", 1); CInventory@ inv = this.getInventory();
if (inv !is null) { if (hasRequirements(inv, reqs, missing)) { server_TakeRequirements(inv, reqs); } else { warn("took a bomb even though we dont have one! SapperLogic.as"); } } else { warn("our inventory was null! SapperLogic.as"); }
}
void onHitBlob(CBlob@ this, Vec2f worldPoint, Vec2f velocity, f32 damage, CBlob@ hitBlob, u8 customData)
{
SapperInfo@ sapper; if (!this.get("sapperInfo", @sapper)) { return; }
}
void onCreateInventoryMenu(CBlob@ this, CBlob@ forBlob, CGridMenu @gridmenu)
{
if (bombTypeNames.length == 0) { return; }
this.ClearGridMenusExceptInventory(); Vec2f pos(gridmenu.getUpperLeftPosition().x + 0.5f * (gridmenu.getLowerRightPosition().x - gridmenu.getUpperLeftPosition().x), gridmenu.getUpperLeftPosition().y - 32 * 1 - 2 * 24); CGridMenu@ menu = CreateGridMenu(pos, this, Vec2f(bombTypeNames.length, 2), "Current bomb"); u8 weaponSel = this.get_u8("bomb type");
if (menu !is null) { menu.deleteAfterClick = false;
for (uint i = 0; i < bombTypeNames.length; i++) { string matname = bombTypeNames[i]; CGridButton @button = menu.AddButton(bombIcons[i], bombNames[i], this.getCommandID("pick " + matname));
if (button !is null) { bool enabled = this.getBlobCount(bombTypeNames[i]) > 0; button.SetEnabled(enabled); button.selectOneOnClick = true; if (weaponSel == i) { button.SetSelected(1); } } } }
}
void onAttach(CBlob@ this, CBlob@ attached, AttachmentPoint @attachedPoint)
{
for (uint i = 0; i < bombTypeNames.length; i++) { if (attached.getName() == bombTypeNames[i]) { this.set_u8("bomb type", i); break; } }
}
void onAddToInventory(CBlob@ this, CBlob@ blob)
{
const string itemname = blob.getName(); if (this.isMyPlayer() && this.getInventory().getItemsCount() > 1) { for (uint j = 1; j < bombTypeNames.length; j++) { if (itemname == bombTypeNames[j]) { SetHelp(this, "help inventory", "sapper", "$Help_Bomb1$$Swap$$Help_Bomb2$ $KEY_TAP$$KEY_F$", "", 2); break; } } }
if (this.getInventory().getItemsCount() == 0 || itemname == "mat_bombs") { for (uint j = 0; j < bombTypeNames.length; j++) { if (itemname == bombTypeNames[j]) { this.set_u8("bomb type", j); return; } } }
}
void SetFirstAvailableBomb(CBlob@ this)
{
u8 type = 255; if (this.exists("bomb type")) type = this.get_u8("bomb type");
CInventory@ inv = this.getInventory();
bool typeReal = (uint(type) < bombTypeNames.length); if (typeReal && inv.getItem(bombTypeNames[type]) !is null) return;
for (int i = 0; i < inv.getItemsCount(); i++) { const string itemname = inv.getItem(i).getName(); for (uint j = 0; j < bombTypeNames.length; j++) { if (itemname == bombTypeNames[j]) { type = j; break; } }
if (type != 255) break; }
this.set_u8("bomb type", type);
}
bool canHit(CBlob@ this, CBlob@ b)
{
if (b.hasTag("invincible")) return false;
// Don't hit temp blobs and items carried by teammates. if (b.isAttached()) {
CBlob@ carrier = b.getCarriedBlob();
if (carrier !is null) if (carrier.hasTag("player") && (this.getTeamNum() == carrier.getTeamNum() || b.hasTag("temp blob"))) return false;
}
if (b.hasTag("dead")) return true;
return b.getTeamNum() != this.getTeamNum();
}