v0.6.4: new ranged weapon, 2 new melee weapons (gauntlet sprite WIP)

This commit is contained in:
Evan Debenham 2018-03-18 18:51:22 -04:00
parent 6c76393f2a
commit 6e63c6db21
13 changed files with 283 additions and 55 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -99,9 +99,11 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfTransfusion;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.AssassinsBlade;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.BattleAxe;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dirk;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Flail;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Gauntlets;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Glaive;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Greataxe;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Greatshield;
@ -130,11 +132,10 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWea
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Shuriken;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingHammer;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingKnife;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingSpear;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Tomahawk;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Trident;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.IncendiaryDart;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.ParalyticDart;
import com.shatteredpixel.shatteredpixeldungeon.plants.BlandfruitBush;
import com.shatteredpixel.shatteredpixeldungeon.plants.Blindweed;
import com.shatteredpixel.shatteredpixeldungeon.plants.Dreamfoil;
@ -299,18 +300,20 @@ public class Generator {
BattleAxe.class,
Flail.class,
RunicBlade.class,
AssassinsBlade.class
AssassinsBlade.class,
Crossbow.class
};
WEP_T4.probs = new float[]{ 6, 5, 5, 4, 4 };
WEP_T4.probs = new float[]{ 6, 5, 5, 4, 4, 4 };
WEP_T5.classes = new Class<?>[]{
Greatsword.class,
WarHammer.class,
Glaive.class,
Greataxe.class,
Greatshield.class
Greatshield.class,
Gauntlets.class
};
WEP_T5.probs = new float[]{ 6, 5, 5, 4, 4 };
WEP_T5.probs = new float[]{ 6, 5, 5, 4, 4, 4 };
//see Generator.randomArmor
ARMOR.classes = new Class<?>[]{
@ -332,14 +335,13 @@ public class Generator {
MIS_T1.probs = new float[]{ 1, 1 };
MIS_T2.classes = new Class<?>[]{
Shuriken.class,
IncendiaryDart.class,
ParalyticDart.class,
FishingSpear.class,
Shuriken.class
};
MIS_T2.probs = new float[]{ 8, 3, 3 };
MIS_T2.probs = new float[]{ 4, 3 };
MIS_T3.classes = new Class<?>[]{
FishingSpear.class,
ThrowingSpear.class,
Bolas.class
};
MIS_T3.probs = new float[]{ 4, 3 };

View File

@ -0,0 +1,41 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2017 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class Crossbow extends MeleeWeapon {
{
image = ItemSpriteSheet.CROSSBOW;
//check Dart.class for additional properties
tier = 4;
}
@Override
public int max(int lvl) {
return 4*(tier+1) + //20 base, down from 25
lvl*(tier); //+4 per level, down from +5
}
}

View File

@ -0,0 +1,47 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2017 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
//TODO rename
public class Gauntlets extends MeleeWeapon {
{
image = ItemSpriteSheet.GAUNTLETS;
tier = 5;
DLY = 0.5f; //2x speed
}
@Override
public int max(int lvl) {
return Math.round(2.5f*(tier+1)) + //15 base, down from 30
lvl*Math.round(0.5f*(tier+1)); //+3 per level, down from +6
}
@Override
public int defenseFactor( Char owner ) {
return 5; //5 extra defence
}
}

View File

@ -21,6 +21,8 @@
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class FishingSpear extends MissileWeapon {
@ -31,22 +33,30 @@ public class FishingSpear extends MissileWeapon {
@Override
public int min(int lvl) {
return 6;
return 4;
}
@Override
public int max(int lvl) {
return 15;
return 10;
}
@Override
public int STRReq(int lvl) {
return 13;
return 11;
}
@Override
public int proc(Char attacker, Char defender, int damage) {
if (defender instanceof Piranha){
damage = Math.max(damage, defender.HP/2);
}
return super.proc(attacker, defender, damage);
}
@Override
public int price() {
return 18 * quantity;
return 12 * quantity;
}
}

View File

@ -0,0 +1,52 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2017 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
public class ThrowingSpear extends MissileWeapon {
{
image = ItemSpriteSheet.THROWING_SPEAR;
}
@Override
public int min(int lvl) {
return 6;
}
@Override
public int max(int lvl) {
return 15;
}
@Override
public int STRReq(int lvl) {
return 13;
}
@Override
public int price() {
return 18 * quantity;
}
}

View File

@ -21,7 +21,11 @@
package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Projecting;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet;
@ -29,18 +33,16 @@ public class Dart extends MissileWeapon {
{
image = ItemSpriteSheet.DART;
bones = false; //Finding them in bones would be semi-frequent and disappointing.
}
@Override
public int min(int lvl) {
return 1;
return bow != null ? 4 + bow.level() : 1;
}
@Override
public int max(int lvl) {
return 2;
return bow != null ? 12 + 3*bow.level() : 2;
}
@Override
@ -53,11 +55,44 @@ public class Dart extends MissileWeapon {
return 0;
}
private static Crossbow bow;
private void updateCrossbow(){
if (Dungeon.hero.belongings.weapon instanceof Crossbow){
bow = (Crossbow) Dungeon.hero.belongings.weapon;
} else {
bow = null;
}
}
@Override
public Item random() {
super.random();
quantity += 3;
return this;
public int throwPos(Hero user, int dst) {
if (bow != null && bow.hasEnchant(Projecting.class)
&& !Dungeon.level.solid[dst] && Dungeon.level.distance(user.pos, dst) <= 4){
return dst;
} else {
return super.throwPos(user, dst);
}
}
@Override
public int proc(Char attacker, Char defender, int damage) {
if (bow != null && bow.enchantment != null){
damage = bow.enchantment.proc(bow, attacker, defender, damage);
}
return super.proc(attacker, defender, damage);
}
@Override
protected void onThrow(int cell) {
updateCrossbow();
super.onThrow(cell);
}
@Override
public String info() {
updateCrossbow();
return super.info();
}
@Override

View File

@ -40,6 +40,10 @@ public class HealingDart extends TippedDart {
Buff.affect( defender, Healing.class ).setHeal((int)(0.5f*defender.HT + 30), 0.333f, 0);
PotionOfHealing.cure( defender );
if (attacker.alignment == defender.alignment){
return 0;
}
return super.proc(attacker, defender, damage);
}

View File

@ -37,6 +37,10 @@ public class HolyDart extends TippedDart {
Buff.affect(defender, Bless.class, 20f);
if (attacker.alignment == defender.alignment){
return 0;
}
return super.proc(attacker, defender, damage);
}
}

View File

@ -68,9 +68,9 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Javelin;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Shuriken;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingHammer;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingSpear;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Tomahawk;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Trident;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.IncendiaryDart;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.TippedDart;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
@ -171,15 +171,15 @@ public class ShopRoom extends SpecialRoom {
case 6:
itemsToSpawn.add( (Random.Int( 2 ) == 0 ? new Shortsword().identify() : new HandAxe()).identify() );
itemsToSpawn.add( Random.Int( 2 ) == 0 ?
new Shuriken().quantity(2) :
new IncendiaryDart().quantity(5));
new FishingSpear().quantity(2) :
new Shuriken().quantity(2));
itemsToSpawn.add( new LeatherArmor().identify() );
break;
case 11:
itemsToSpawn.add( (Random.Int( 2 ) == 0 ? new Sword().identify() : new Mace()).identify() );
itemsToSpawn.add( Random.Int( 2 ) == 0 ?
new FishingSpear().quantity(2) :
new ThrowingSpear().quantity(2) :
new Bolas().quantity(2));
itemsToSpawn.add( new MailArmor().identify() );
break;

View File

@ -182,12 +182,14 @@ public class ItemSpriteSheet {
public static final int FLAIL = WEP_TIER4+2;
public static final int RUNIC_BLADE = WEP_TIER4+3;
public static final int ASSASSINS_BLADE = WEP_TIER4+4;
public static final int CROSSBOW = WEP_TIER4+5;
static{
assignItemRect(LONGSWORD, 15, 15);
assignItemRect(BATTLE_AXE, 16, 16);
assignItemRect(FLAIL, 14, 14);
assignItemRect(RUNIC_BLADE, 14, 14);
assignItemRect(ASSASSINS_BLADE, 14, 15);
assignItemRect(CROSSBOW, 15, 15);
}
private static final int WEP_TIER5 = xy(1, 9); //8 slots
@ -196,12 +198,14 @@ public class ItemSpriteSheet {
public static final int GLAIVE = WEP_TIER5+2;
public static final int GREATAXE = WEP_TIER5+3;
public static final int GREATSHIELD = WEP_TIER5+4;
public static final int GAUNTLETS = WEP_TIER5+5;
static{
assignItemRect(GREATSWORD, 16, 16);
assignItemRect(WAR_HAMMER, 16, 16);
assignItemRect(GLAIVE, 16, 16);
assignItemRect(GREATAXE, 12, 16);
assignItemRect(GREATSHIELD, 12, 16);
assignItemRect(GAUNTLETS, 13, 15);
}
//8 free slots
@ -213,9 +217,10 @@ public class ItemSpriteSheet {
public static final int THROWING_KNIFE = MISSILE_WEP+2;
public static final int THROWING_STONE = MISSILE_WEP+3;
public static final int SHURIKEN = MISSILE_WEP+4;
public static final int FISHING_SPEAR = MISSILE_WEP+4;
public static final int SHURIKEN = MISSILE_WEP+5;
public static final int FISHING_SPEAR = MISSILE_WEP+7;
public static final int THROWING_SPEAR = MISSILE_WEP+7;
public static final int BOLAS = MISSILE_WEP+8;
public static final int JAVELIN = MISSILE_WEP+10;
@ -231,9 +236,10 @@ public class ItemSpriteSheet {
assignItemRect(THROWING_KNIFE, 12, 13);
assignItemRect(THROWING_STONE, 9, 9);
assignItemRect(FISHING_SPEAR, 11, 11);
assignItemRect(SHURIKEN, 12, 12);
assignItemRect(FISHING_SPEAR, 13, 13);
assignItemRect(THROWING_SPEAR, 13, 13);
assignItemRect(BOLAS, 15, 14);
assignItemRect(JAVELIN, 16, 16);

View File

@ -21,7 +21,18 @@
package com.shatteredpixel.shatteredpixeldungeon.sprites;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Crossbow;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Bolas;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Boomerang;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.FishingSpear;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Javelin;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Shuriken;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingKnife;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.ThrowingSpear;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.Trident;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Dart;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.noosa.Visual;
import com.watabou.noosa.tweeners.PosTweener;
@ -55,41 +66,37 @@ public class MissileSprite extends ItemSprite implements Tweener.Listener {
public void reset( PointF from, PointF to, Item item, Callback listener) {
revive();
int image;
if (item == null) view(image = 0, null);
else view(image = item.image(), item.glowing());
if (item == null) view(0, null);
else view(item.image(), item.glowing());
setup( from,
to,
image,
item,
listener );
}
private static final int DEFAULT_ANGULAR_SPEED = 720;
private static final HashMap<Integer, Integer> ANGULAR_SPEEDS = new HashMap<>();
private static final HashMap<Class<?extends Item>, Integer> ANGULAR_SPEEDS = new HashMap<>();
static {
ANGULAR_SPEEDS.put(ItemSpriteSheet.DART, 0);
ANGULAR_SPEEDS.put(ItemSpriteSheet.THROWING_KNIFE, 0);
ANGULAR_SPEEDS.put(ItemSpriteSheet.FISHING_SPEAR, 0);
ANGULAR_SPEEDS.put(ItemSpriteSheet.JAVELIN, 0);
ANGULAR_SPEEDS.put(ItemSpriteSheet.TRIDENT, 0);
for( int i = ItemSpriteSheet.TIPPED_DARTS; i < ItemSpriteSheet.TIPPED_DARTS+16; i++){
ANGULAR_SPEEDS.put(i, 0);
}
ANGULAR_SPEEDS.put(Dart.class, 0);
ANGULAR_SPEEDS.put(ThrowingKnife.class, 0);
ANGULAR_SPEEDS.put(FishingSpear.class, 0);
ANGULAR_SPEEDS.put(ThrowingSpear.class, 0);
ANGULAR_SPEEDS.put(Javelin.class, 0);
ANGULAR_SPEEDS.put(Trident.class, 0);
//720 is default
ANGULAR_SPEEDS.put(ItemSpriteSheet.BOOMERANG, 1440);
ANGULAR_SPEEDS.put(ItemSpriteSheet.BOLAS, 1440);
ANGULAR_SPEEDS.put(Boomerang.class, 1440);
ANGULAR_SPEEDS.put(Bolas.class, 1440);
ANGULAR_SPEEDS.put(ItemSpriteSheet.SHURIKEN, 2160);
ANGULAR_SPEEDS.put(Shuriken.class, 2160);
}
//TODO it might be nice to have a source and destination angle, to improve thrown weapon visuals
private void setup( PointF from, PointF to, int image, Callback listener ){
private void setup( PointF from, PointF to, Item item, Callback listener ){
originToCenter();
@ -98,10 +105,15 @@ public class MissileSprite extends ItemSprite implements Tweener.Listener {
point( from );
PointF d = PointF.diff( to, from );
speed.set( d ).normalize().scale( SPEED );
if ( ANGULAR_SPEEDS.containsKey(image)) angularSpeed = ANGULAR_SPEEDS.get(image);
else angularSpeed = DEFAULT_ANGULAR_SPEED;
speed.set(d).normalize().scale(SPEED);
angularSpeed = DEFAULT_ANGULAR_SPEED;
for (Class<?extends Item> cls : ANGULAR_SPEEDS.keySet()){
if (cls.isAssignableFrom(item.getClass())){
angularSpeed = ANGULAR_SPEEDS.get(cls);
break;
}
}
angle = 135 - (float)(Math.atan2( d.x, d.y ) / 3.1415926 * 180);
@ -116,7 +128,11 @@ public class MissileSprite extends ItemSprite implements Tweener.Listener {
updateFrame();
}
PosTweener tweener = new PosTweener( this, to, d.length() / SPEED );
float speed = SPEED;
if (item instanceof Dart && Dungeon.hero.belongings.weapon instanceof Crossbow){
speed *= 3f;
}
PosTweener tweener = new PosTweener( this, to, d.length() / speed );
tweener.listener = this;
parent.add( tweener );
}

View File

@ -822,6 +822,10 @@ items.weapon.melee.battleaxe.name=battle axe
items.weapon.melee.battleaxe.stats_desc=This is a rather accurate weapon.
items.weapon.melee.battleaxe.desc=The enormous steel head of this battle axe puts considerable heft behind each wide stroke.
items.weapon.melee.crossbow.name=crossbow
items.weapon.melee.crossbow.stats_desc=This weapon enhances the damage of thrown darts when equipped, and will even grant its enchantment to them.
items.weapon.melee.crossbow.desc=A fairly intricate weapon which shoots bolts at exceptional speeds. While it isn't designed for it, this crossbow's heft and sturdy construction make it a decent melee weapon as well.
items.weapon.melee.dagger.name=dagger
items.weapon.melee.dagger.stats_desc=This weapon is stronger against unaware enemies.
items.weapon.melee.dagger.desc=A simple iron dagger with a worn wooden handle.
@ -834,6 +838,10 @@ items.weapon.melee.flail.name=flail
items.weapon.melee.flail.stats_desc=This is a rather inaccurate weapon.\nThis weapon cannot surprise attack.
items.weapon.melee.flail.desc=A spiked ball attached to a handle by a length of chain. Very unwieldy, but devastating if it lands a solid hit.
items.weapon.melee.gauntlets.name=stone gauntlets
items.weapon.melee.gauntlets.stats_desc=This is a very fast weapon.\nThis weapon blocks some damage.
items.weapon.melee.gauntlets.desc=These large gauntlets are made of crimson fabric with heavy magical stone layered ontop. They tighten around your arms and add tremendous force to your blows.
items.weapon.melee.glaive.name=glaive
items.weapon.melee.glaive.stats_desc=This is a rather slow weapon.\nThis weapon has extra reach.
items.weapon.melee.glaive.desc=A massive polearm consisting of a sword blade on the end of a pole.
@ -977,7 +985,7 @@ items.weapon.missiles.curaredart.name=curare dart
items.weapon.missiles.curaredart.desc=These darts are tipped with an earthroot-based compound which will paralyze their target for a short time.
items.weapon.missiles.fishingspear.name=fishing spear
items.weapon.missiles.fishingspear.desc=Lightweight throwing spears designed for fishing. They work well as an improvised weapon too.
items.weapon.missiles.fishingspear.desc=Tiny throwing spears designed for fishing. They work well as an improvised weapon too.
items.weapon.missiles.javelin.name=javelin
items.weapon.missiles.javelin.desc=These larger throwing spears are weighted to keep the spike at their tip foremost as they sail through the air.
@ -996,6 +1004,9 @@ items.weapon.missiles.throwinghammer.desc=These hefty hammers are designed to be
items.weapon.missiles.throwingknife.name=throwing knife
items.weapon.missiles.throwingknife.desc=These lightweight knives are balanced to arc through the air right into their target. They are most effective against unaware enemies.
items.weapon.missiles.throwingspear.name=throwing spear
items.weapon.missiles.throwingspear.desc=These lightweight spears have thin frames which are clearly designed to be thrown, and not thrusted.
items.weapon.missiles.throwingstone.name=throwing stone
items.weapon.missiles.throwingstone.desc=These stones are sanded down to make them able to be thrown with more power than a regular stone. Despite the craftsmanship, they still aren't a very reliable weapon.