@Override
	public void executeMsg(final Environmental myHost, final CMMsg msg)
	{
		super.executeMsg(myHost,msg);

		switch(msg.sourceMinor())
		{
		case CMMsg.TYP_HUH:
		case CMMsg.TYP_COMMANDFAIL:
		case CMMsg.TYP_COMMAND:
			break;
		default:
			if((msg.source().riding()==this)
			||(msg.othersMessage()==null)
			)
				this.sendAreaMessage(msg, true);
			else
			{
				final CMMsg msg2=(CMMsg)msg.copyOf();
				msg2.setOthersMessage(L("^HOff the deck you see: ^N")+msg.othersMessage());
				sendAreaMessage(msg2, true);
			}
		}
		
		if(msg.target() == this)
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LOOK:
			case CMMsg.TYP_EXAMINE:
			{
				final StringBuilder visualCondition = new StringBuilder("");
				if(this.anchorDown)
					visualCondition.append(L("^HThe anchor on @x1 is lowered, holding her in place.^.^?",name(msg.source())));
				else
				if((this.courseDirection >= 0)
				&&((this.courseDirections.size()>0)&&(this.courseDirections.get(0).intValue()>=0)))
					visualCondition.append(L("^H@x1 is under full sail, traveling @x2^.^?",CMStrings.capitalizeFirstLetter(name(msg.source())), CMLib.directions().getDirectionName(courseDirection & 127)));
				if(this.subjectToWearAndTear() && (usesRemaining() <= 100))
				{
					final double pct=(CMath.div(usesRemaining(),100.0));
					appendCondition(visualCondition,pct,name(msg.source()));
				}
				if(visualCondition.length()>0)
				{
					msg.addTrailerRunnable(new Runnable()
					{
						@Override
						public void run()
						{
							msg.source().tell(visualCondition.toString());
						}
					});
				}
				break;
			}
			default:
				break;
			}
		}
		
		if((msg.target() instanceof Room)
		&&(msg.target() == owner()))
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LOOK:
			case CMMsg.TYP_EXAMINE:
				if((CMLib.map().areaLocation(msg.source())==area))
				{
					final StringBuilder visualCondition = new StringBuilder("");
					if(this.anchorDown)
						visualCondition.append(L("\n\r^HThe anchor on @x1 is lowered, holding her in place.^.^?",name(msg.source())));
					else
					if((this.courseDirection >= 0)
					&&((this.courseDirections.size()>0)&&(this.courseDirections.get(0).intValue()>=0)))
						visualCondition.append(L("\n\r^H@x1 is under full sail, traveling @x2^.^?",name(msg.source()), CMLib.directions().getDirectionName(courseDirection & 127)));
					if(this.subjectToWearAndTear() && (usesRemaining() <= 100) && (this.targetedShip != null))
					{
						final double pct=(CMath.div(usesRemaining(),100.0));
						appendCondition(visualCondition,pct,name(msg.source()));
					}
					if(visualCondition.length()>0)
						msg.addTrailerMsg(CMClass.getMsg(msg.source(), null, null, CMMsg.MSG_OK_VISUAL, visualCondition.toString(), -1, null, -1, null));
				}
				break;
			case CMMsg.TYP_LEAVE:
			case CMMsg.TYP_ENTER:
				if((owner() instanceof Room)
				&&(msg.target() instanceof Room)
				&&(((Room)msg.target()).getArea()!=area))
				{
					if(((msg.source().riding() == this)
						&&(msg.source().Name().equals(Name())))
					||((this.targetedShip!=null)
						&&(msg.source().riding() == targetedShip)
						&&(msg.source().Name().equals(targetedShip.Name()))))
					{
						clearTacticalMode();
					}
				}
				break;
			}
		}
		else
		if(msg.target()  == this)
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_ENTER:
				break;
			case CMMsg.TYP_WEAPONATTACK:
				if(msg.targetMinor()==CMMsg.TYP_WEAPONATTACK)
				{
					Weapon weapon=null;
					if((msg.tool() instanceof Weapon))
						weapon=(Weapon)msg.tool();
					if((weapon!=null)&&(msg.source().riding()!=null)&&(owner() instanceof Room))
					{
						final Room shipRoom=(Room)owner();
						final boolean isHit=msg.value()>0;
						if(isHit && CMLib.combat().isAShipSiegeWeapon(weapon) 
						&& (((AmmunitionWeapon)weapon).ammunitionCapacity() > 1))
						{
							int shotsRemaining = ((AmmunitionWeapon)weapon).ammunitionRemaining() + 1;
							((AmmunitionWeapon)weapon).setAmmoRemaining(0);
							final Area A=this.getShipArea();
							ArrayList<Pair<MOB,Room>> targets = new ArrayList<Pair<MOB,Room>>(5);
							if(A!=null)
							{
								for(Enumeration<Room> r=A.getProperMap();r.hasMoreElements();)
								{
									final Room R=r.nextElement();
									if((R!=null)&&((R.domainType()&Room.INDOORS)==0))
									{
										for(Enumeration<MOB> m=R.inhabitants();m.hasMoreElements();)
											targets.add(new Pair<MOB,Room>(m.nextElement(),R));
									}
								}
							}
							final int chanceToHit = targets.size() * 20;
							final Room oldRoom=msg.source().location();
							try
							{
								final double pctLoss = CMath.div(msg.value(), 100.0);
								while(shotsRemaining-- > 0)
								{
									final Pair<MOB,Room> randomPair = (targets.size()>0)? targets.get(CMLib.dice().roll(1,targets.size(),-1)) : null;
									if((CMLib.dice().rollPercentage() < chanceToHit)&&(randomPair != null))
									{
										msg.source().setLocation(shipRoom);
										int pointsLost = (int)Math.round(pctLoss * msg.source().maxState().getHitPoints());
										CMLib.combat().postWeaponDamage(msg.source(), randomPair.first, weapon, pointsLost);
									}
									else
									if(randomPair != null)
									{
										msg.source().setLocation(shipRoom);
										CMLib.combat().postWeaponAttackResult(msg.source(), randomPair.first, weapon, false);
									}
									else
									{
										this.announceActionToDeck(msg.source(), msg.target(), weapon, weapon.missString());
									}
								}
							}
							finally
							{
								msg.source().setLocation(oldRoom);
							}
						}
						else
							CMLib.combat().postShipWeaponAttackResult(msg.source(), msg.source().riding(), this, weapon, isHit);
					}
				}
				break;
			case CMMsg.TYP_DAMAGE:
				if(msg.value() > 0)
				{
					final int maxHullPoints = CMLib.combat().getShipHullPoints(this);
					double pctLoss = CMath.div(msg.value(), maxHullPoints);
					int pointsLost = (int)Math.round(pctLoss * maxHullPoints);
					if(pointsLost > 0)
					{
						int weaponType = (msg.tool() instanceof Weapon) ? ((Weapon)msg.tool()).weaponDamageType() : Weapon.TYPE_BASHING;
						final String hitWord = CMLib.combat().standardHitWord(weaponType, pctLoss);
						final String msgStr = (msg.targetMessage() == null) ? L("<O-NAME> fired from <S-NAME> hits and @x1 @x2.",hitWord,name()) : msg.targetMessage();
						final CMMsg deckHitMsg=CMClass.getMsg(msg.source(), this, msg.tool(),CMMsg.MSG_OK_ACTION, msgStr);
						this.announceActionToDeckOrUnderdeck(msg.source(), deckHitMsg, 0);
						final CMMsg underdeckHitMsg=CMClass.getMsg(msg.source(), this, msg.tool(),CMMsg.MSG_OK_ACTION, L("Something hits and @x1 the ship.",hitWord));
						this.announceActionToDeckOrUnderdeck(msg.source(), underdeckHitMsg, Room.INDOORS);
						if(pointsLost >= this.usesRemaining())
						{
							this.setUsesRemaining(0);
							this.recoverPhyStats(); // takes away the swimmability!
							final Room shipR=CMLib.map().roomLocation(this);
							if(shipR!=null)
							{
								CMLib.tracking().makeSink(this, shipR, false);
								final String sinkString = L("<T-NAME> start(s) sinking!");
								shipR.show(msg.source(), this, CMMsg.MSG_OK_ACTION, sinkString);
								this.announceActionToUnderDeck(msg.source(), sinkString);
							}
							
							if(!CMLib.leveler().postExperienceToAllAboard(msg.source().riding(), 500))
								CMLib.leveler().postExperience(msg.source(), null, null, 500, false);
							this.clearTacticalMode();
						}
						else
						{
							this.setUsesRemaining(this.usesRemaining() - pointsLost);
						}
					}
				}
				break;
			}
		}
		else
		if(msg.target() instanceof AmmunitionWeapon)
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_RELOAD:
				if((msg.tool() instanceof Ammunition)
				&&(CMLib.combat().isAShipSiegeWeapon((Item)msg.target())))
				{
					final MOB tellM=msg.source();
					final Item I= (Item)msg.target();
					msg.addTrailerRunnable(new Runnable()
					{
						@Override
						public void run()
						{
							tellM.tell(L("@x1 is now loaded. Don't forget to aim.",I.name()));
						}
					});
				}
				break;
			}
		}
		else
		{
			switch(msg.targetMinor())
			{
			case CMMsg.TYP_LOOK:
			case CMMsg.TYP_EXAMINE:
				if((msg.target() instanceof BoardableShip)
				&&(msg.target() instanceof Rideable)
				&&(msg.target()!=this))
				{
					final String otherShipInfo=getOtherShipInfo((Rideable)msg.target());
					if(otherShipInfo.length()>0)
					{
						msg.addTrailerRunnable(new Runnable()
						{
							@Override
							public void run()
							{
								msg.source().tell(otherShipInfo);
							}
						});
					}
				}
				break;
			}
		}
			
	}