Skip to content
This repository has been archived by the owner on Jul 11, 2018. It is now read-only.

Commit

Permalink
1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
alejandroliu committed Oct 31, 2016
1 parent f3d5343 commit 7a0f000
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 84 deletions.
55 changes: 45 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,72 @@ Overview
Let's you play a simulation of the old PC game
[Scorched Earth](http://en.wikipedia.org/wiki/Scorched_Earth_%28video_game%29).

Command:
Commands:

* *fire* _[speed]_ _[fuse]_
* *rpg* _[fuse speed|short|long|fast]_
* *fire* _[fuse speed|short|long|fast]_

Documentation
-------------

*WARNING: This game is very destructive to world maps.*

Let's you play a game similar to
[Scorched Earth](http://en.wikipedia.org/wiki/Scorched_Earth_%28video_game%29).

You are given a RPG which you can use to fire grenades (TNT) to your
opponent using the `/fire` command.
You need to have a bow, at least one arrow and as many TNT's as you
can muster.

Equip the bow. And then enter the command:

/rpg fast

Activates the RPG with default settings. Now start shooting your
bow. Instead of arrows, you will find Primed TNTs.

With this you can play a
[Scorched Earth](http://en.wikipedia.org/wiki/Scorched_Earth_%28video_game%29).
like game.

The grenade is sent in the direction you are facing. Looking up or
down controls the angle of elevation (thus the distance fired).
Looking up or down controls the angle of elevation (thus the distance fired).

You can tweak the grenade by optionally specifying an initial _speed_
and a _fuse_ setting.
You can tweak the grenade by optionally specifying an initial _fuse_
and a _speed_ setting.

The game is played with two or more players in different locations in
the map, and they trade shots until only one remains.

WARNING: This game is very destructive to world maps.
The _fuse_ is the time (in ticks) that the grenade will explode.
Be careful of using very short fuses. The _speed_ is the initial
speed of the grenade. Faster means the TNT will travel farther.

### Presets:

* short: fuse=30, speed=0.5
* long: fuse=80, speed=1.0
* fast: fuse=20, speed=1.0

### Permission Nodes:

* scorched.cmd.fire - access to the fire command.
* scorched.cmd.fire - access to commands.

### TODO

* There are two events, ExplosionPrimeEvent for when the entity is
about to explode and EntityExplodeEvent when actually exploding.
* Catch ExplosionPrimeEvent so we can have an option to disable block
breaking (setBlockBreaking false)... Anti personel grenade.
* Needs to add a namedtag to indicate is one of our grenades.
* EntityExplodeEvent can change the yield? Mega grenateds?
* Maybe we can add random cancel to ExplosionPrimeEvent so there is
a misfired grenade resulting in lying around ordenance.
* Does the bow get damage? A damaged bow should have a chance to
explode.

Changes
-------

* 1.1.0 : Playability improvements
* 1.0.0 : First release

Copyright
Expand Down
9 changes: 6 additions & 3 deletions plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ load: POSTWORLD

name: Scorched
description: The Mother of All Mini-Games
version: 1.0.0
version: 1.1.0
author: aliuly

commands:
rpg:
description: Arm RPG
usage: "/rpg [fuse speed|short|long|fast]"
fire:
description: Fire RPG
usage: "/fire [speed] [fuse]"
description: Fire grenade
usage: "/fire [fuse speed|short|long|fast]"

permissions:
scorched.cmd.fire:
Expand Down
212 changes: 141 additions & 71 deletions src/aliuly/scorched/Main.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use pocketmine\Server;
use pocketmine\utils\TextFormat;

use pocketmine\event\Listener;
use pocketmine\item\Item;
use pocketmine\entity\Entity;
use pocketmine\nbt\tag\Byte;
Expand All @@ -18,7 +19,17 @@
use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Float;

class Main extends PluginBase implements CommandExecutor {
use pocketmine\event\player\PlayerItemHeldEvent;
use pocketmine\event\entity\EntityShootBowEvent;

class Main extends PluginBase implements CommandExecutor, Listener {
protected $shooters;
static $presets = [
"short" => [30, 0.5],
"long" => [80, 1.0],
"fast" => [20, 1.0],
];

// Access and other permission related checks
private function access(CommandSender $sender, $permission) {
if($sender->hasPermission($permission)) return true;
Expand All @@ -31,107 +42,166 @@ private function inGame(CommandSender $sender,$msg = true) {
return false;
}

// Paginate output
private function getPageNumber(array &$args) {
$pageNumber = 1;
if (count($args) && is_numeric($args[count($args)-1])) {
$pageNumber = (int)array_pop($args);
if($pageNumber <= 0) $pageNumber = 1;
}
return $pageNumber;
}
private function paginateText(CommandSender $sender,$pageNumber,array $txt) {
$hdr = array_shift($txt);
if($sender instanceof ConsoleCommandSender){
$sender->sendMessage( TextFormat::GREEN.$hdr.TextFormat::RESET);
foreach ($txt as $ln) $sender->sendMessage($ln);
return true;
// Event handlers
public function onItemHeld(PlayerItemHeldEvent $e) {
$p = $e->getPlayer();
$n = $p->getName();
if (!isset($this->shooters[$n])) return;
if ($e->getItem()->getID() != Item::BOW) {
unset($this->shooters[$n]);
$p->sendMessage("Disarming RPG");
}
$pageHeight = 5;
$hdr = TextFormat::GREEN.$hdr. TextFormat::RESET;
if (($pageNumber-1) * $pageHeight >= count($txt)) {
$sender->sendMessage($hdr);
$sender->sendMessage("Only ".intval(count($txt)/$pageHeight+1)." pages available");
return true;
}
$hdr .= TextFormat::RED." ($pageNumber of ".intval(count($txt)/$pageHeight+1).")".TextFormat::RESET;
$sender->sendMessage($hdr);
for ($ln = ($pageNumber-1)*$pageHeight;$ln < count($txt) && $pageHeight--;++$ln) {
$sender->sendMessage($txt[$ln]);
}
return true;
}
private function paginateTable(CommandSender $sender,$pageNumber,array $tab) {
$cols = [];
for($i=0;$i < count($tab[0]);$i++) $cols[$i] = strlen($tab[0][$i]);
foreach ($tab as $row) {
for($i=0;$i < count($row);$i++) {
if (($l=strlen($row[$i])) > $cols[$i]) $cols[$i] = $l;
public function onShoot(EntityShootBowEvent $e) {
$p = $e->getEntity();
if (!($p instanceof Player)) return;
$n = $p->getName();
if (!isset($this->shooters[$n])) return;
if ($e->isCancelled()) return;
if (!isset($this->shooters[$n])) return;
$e->setCancelled(); // Disable it and replace it with our own

if (!$p->isCreative()) {
if (!$this->checkAmmo($p,true)) {
$p->sendMessage("You are out of grenades");
$p->sendMessage("RPG disarmed");
unset($this->shoters[$n]);
return;
}
}
$txt = [];
foreach ($tab as $row) {
$txt[] = sprintf("%-$cols[0]s %-$cols[1]s %-$cols[2]s %-$cols[3]s",
$row[0],$row[1],$row[2],$row[3]);
}
return $this->paginateText($sender,$pageNumber,$txt);

// $e->getBow(); // Check if damage and if below number can malfunction
// $e->getForce(); // always returns the same value of 1.5!

$this->fire($p,$this->shooters[$n][0],$this->shooters[$n][1]);
}

// Standard call-backs
public function onDisable() {
$this->getLogger()->info("- Scorched Unloaded!");
//$this->getLogger()->info("- Scorched Unloaded!");
}
public function onEnable(){
$this->getLogger()->info("* Scorched Enabled!");
//$this->getLogger()->info("* Scorched Enabled!");
$this->shooters = [];
$this->getServer()->getPluginManager()->registerEvents($this, $this);
}
public function onCommand(CommandSender $sender, Command $cmd, $label, array $args) {
switch($cmd->getName()) {
case "rpg":
if (!$this->access($sender,"scorched.cmd.fire")) return true;
return $this->cmdRpg($sender,$args);
case "fire":
if (!$this->access($sender,"scorched.cmd.fire")) return true;
return $this->cmdMain($sender,$args);
return $this->cmdFire($sender,$args);
}
return false;
}
// Command implementations

private function cmdMain(CommandSender $c,$args) {
if (!$this->inGame($c)) return false;
if (!$c->isCreative()) {
// Not in creative, we need to check inventories...
$found = false;
foreach ($c->getInventory()->getContents() as $slot=>$item) {
if ($item->getID() != Item::TNT || $item->getCount() == 0) continue;
private function checkAmmo(Player $p,$adj=false) {
foreach ($p->getInventory()->getContents() as $slot=>$item) {
if ($item->getID() != Item::TNT || $item->getCount() == 0) continue;

$found = true;
if ($adj) {
$count = $item->getCount();
if ($count == 1) {
// The last one...
$c->getInventory()->clear($slot);
$p->getInventory()->clear($slot);
} else {
$item->setCount($count-1);
$c->getInventory()->setItem($slot,$item);
$p->getInventory()->setItem($slot,$item);
}
break;
}
if (!$found) {
$c->sendMessage(TextFormat::RED."You ran out of rockets".TextFormat::RESET);
return true;
}
return true;
}
$pos = $c->getPosition();
$pos->y += $c->getEyeHeight();
$speed = 2.5;
if (isset($args[0]) && is_numeric($args[0])) {
$speed = (float)$args[0];
// Run out of grenades, disarm ...
if (isset($this->shooters[$p->getName()])) {
unset($this->shooters[$p->getName()]);
}
return false;
}

// Command implementations
private function cmdFire(CommandSender $c,$args) {
if (!$this->inGame($c)) return false;

$fuse = 40;
$speed = 0.75;

if (count($args)) {
if (isset(self::$presets[$args[0]])) $args = self::$presets[$args[0]];
if (count($args) != 2) return false;
$fuse = (int)$args[0];
$speed = (float)$args[1];
if ($speed > 4.0) $speed = 4.0;
if ($speed < 0.5) $speed = 0.5;
}
$fuse = 80;
if (isset($args[1]) && is_numeric($args[1])) {
$fuse = (int)$args[1];
if ($fuse > 120) $fuse = 120;
if ($fuse < 10) $fuse = 10;
}
if (count($args) > 2) return false;

if (!$c->isCreative()) {
// Not in creative, we need to check inventories...
if (!$this->checkAmmo($c,true)) {
$c->sendMessage("Unable to fire RPG, you are out of grenades");
return true;
}
}
$c->sendMessage("Firing...");
$this->fire($c,$fuse,$speed);
return true;
}
private function cmdRpg(CommandSender $c,$args) {
if (!$this->inGame($c)) return false;
$n = $c->getName();
if (count($args) == 0) {
if (isset($this->shooters[$n])) {
$c->sendMessage("RPG armed");
$c->sendMessage("- Fuse: ".$this->shooters[$n][0]);
$c->sendMessage("- Speed: ".$this->shooters[$n][1]);
} else {
$c->sendMessage("RPG not armed");
}
return true;
}
if ($args[0] == "disarm" || $args[0] == "off") {
if (isset($this->shooters[$n])) {
unset($this->shooters[$n]);
$c->sendMessage("Disarming RPG");
return true;
}
$c->sendMessage("RPG disarmed");
return true;
}
if (!$c->isCreative()) {
// Not in creative, we need to check inventories...
if (!$this->checkAmmo($c)) {
$c->sendMessage("Unable to arm RPG, you are out of grenades");
return true;
}
}
$hand = $c->getInventory()->getItemInHand();
if ($hand->getID() != Item::BOW) {
$c->sendMessage("Unable to arm RPG, you must be holding a Bow");
return true;
}

if (isset(self::$presets[$args[0]])) $args = self::$presets[$args[0]];
if (count($args) != 2) return false;
$fuse = (int)$args[0];
$speed = (float)$args[1];
if ($speed > 4.0) $speed = 4.0;
if ($speed < 0.5) $speed = 0.5;
if ($fuse > 120) $fuse = 120;
if ($fuse < 10) $fuse = 10;

$this->shooters[$n] = [(int)$fuse,(float)$speed];
$c->sendMessage("RPG armed!");
return true;
}


private function fire(Player $c,$fuse,$speed) {
$pos = $c->getPosition();
$pos->y += $c->getEyeHeight();
$speed = 2.5;

$dir = $c->getDirectionVector();
$dir->x = $dir->x * $speed;
Expand Down

0 comments on commit 7a0f000

Please sign in to comment.