Item tempChosenWeapon = myInventory.chooseItem();
this is an Item.  Not a type descended from Item.  It is an Item.
Values in C++ have known types.
cout << tempChosenWeapon.getName() << endl;
all good, but please stop using namespace std;
Item *chosenWeapon = &tempChosenWeapon;
This is a pointer to an Item.  I can prove it is not polymorphic, because it is a pointer to a instance of type Item.  The compiler can probably prove it to.
cout << chosenWeapon->getName() << endl;//THE CODE WORKS UP TO HERE
ok, this repeats the previous call.
Weapon *maybeWeapon = dynamic_cast<Weapon*>(chosenWeapon);
This deterministically returns nullptr.  chosenWeapon is an Item* that we know points to an Item, and an Item is not a Weapon.
cout << maybeWeapon->getName() << endl;
this dereferences nullptr.
There are a number of ways to handle polymorphism in C++.  But you have to think about it.
First, do you want value semantics?  Value sematnics means that a copy of something is a copy of it.  Things don't refer to other things; they are those things.
You can do value semantics with polymorphic values, but it takes a bit of work.  You write two classes; the value wrapper, and the internal pImpl.
The internal pImpl has a std::unique_ptr<Impl> Impl->clone() const method, and the value wrapper calls it when you copy it.
You write your interface like this:
template<class D>
struct clonable {
  std::unique_ptr<D> clone() const = 0;
};
struct ITarget;
struct IItem:clonable<IItem> {
  virtual std::string get_name() const = 0;
  virtual bool can_equip( ITarget const& ) const = 0;
  ~virtual IItem() {}
};
struct Target;
struct Item {
  using Impl = IItem;
  explicit operator bool() const { return (bool)pImpl; }
  IItem* get_impl() { return pImpl.get(); }
  IItem const* get_impl() const { return pImpl.get(); }
  template<class D>
  D copy_and_downcast() const& {
    auto* ptr = dynamic_cast<typename D::Impl const*>( pImpl.get() );
    if (!ptr) return {};
    return D(ptr->clone());
  }
  template<class D>
  D copy_and_downcast() && {
    auto* ptr = dynamic_cast<typename D::Impl*>( pImpl.get() );
    if (!ptr) return {};
    pImpl.release();
    return D(std::unique_ptr<typename D::Impl>(ptr));
  }
  std::string get_name() const {
    if (!*this) return {};
    return pImpl->get_name();
  }
  bool can_equip(Target const& target)const{
    if (!*this) return false;
    if (!target) return false;
    return pImpl->can_equip( *target.get_impl() );
  }
  Item() = default;
  Item(Item&&) = default;
  Item& operator=(Item&&) = default;
  Item(std::unique_ptr<IItem> o):pImpl(std::move(o)) {}
  Item(Item const& o):
    Item( o?Item(o.pImpl->clone()):Item{} )
  {}
  Item& operator=( Item const& o ) {
    Item tmp(o);
    std::swap(pImpl, tmp.pImpl);
    return *this;
  }
private:
  std::unique_ptr<IItem> pImpl;
};
which probably has bugs and is maybe too complex for you.
Second, you can go with reference semantics.
In this case, you want to return shared_ptr<const T> or shared_ptr<T> from your data.  Or you can go half way and return a unique_ptr<T> copy from your chooseItem functions.
Reference semantics is really hard to get right.  But you do get to use dynamic_cast or dynamic_pointer_cast directly.
std::shared_ptr<Item> chosenWeapon = myInventory.chooseItem();
if (!chosenWeapon) return;
std::cout << chosenWeapon->getName() << std::endl;
auto maybeWeapon = dynamic_pointer_cast<Weapon>(chosenWeapon);
if (maybeWeapon)
  std::cout << maybeWeapon->getName() << std::endl;
else
  std::cout << "Not a weapon" << std::endl;